Ответ 1
Кто-нибудь знает, почему методы async не могут иметь аргументы ref и out?
Конечно. Подумайте об этом - метод async обычно возвращается почти сразу, задолго до того, как выполняется большая часть фактической логики... которая выполняется асинхронно. Таким образом, любые параметры out
должны быть назначены перед первым выражением await
, и, возможно, должно быть какое-то ограничение на параметры ref
, чтобы они не могли использоваться после первого выражения await
так как после этого они могут быть даже недействительными.
Рассмотрим метод async с параметрами out
и ref
, используя локальные переменные для аргументов:
int x;
int y = 10;
FooAsync(out x, ref y);
После возврата FooAsync
сам метод может вернуться - так что локальные переменные больше не будут логически существовать... но метод async все равно сможет эффективно использовать их в своих продолжениях. Большие проблемы. Компилятор может создать новый класс для захвата переменной таким же образом, как и для лямбда-выражений, но это может вызвать другие проблемы... кроме всего прочего, вы можете изменить локальную переменную в произвольных точках с помощью метода, когда продолжения выполняются в другом потоке. Как ни странно.
В принципе, нет смысла использовать параметры out
и ref
для методов async
из-за задействованного времени. Используйте тип возврата, который включает все интересующие вас данные.
Если вас интересуют параметры out
и ref
, изменяющиеся до первого выражения await
, вы всегда можете разделить метод на два:
public Task<string> FooAsync(out int x, ref int y)
{
// Assign a value to x here, maybe change y
return FooAsyncImpl(x, y);
}
private async Task<string> FooAsyncImpl(int x, int y) // Not ref or out!
{
}
EDIT: было бы возможно иметь параметры out
, используя Task<T>
, и присваивать значение непосредственно в методе точно так же, как возвращаемые значения. Было бы немного странно, и это не сработало бы для параметров ref
.