argumentos ref y out en el método asíncrono

argumentos ref y out en el método asíncrono

Por supuesto. Piénselo:un método asíncrono generalmente regresa casi inmediatamente, mucho antes de que se ejecute la mayor parte de la lógica real... eso se hace de forma asíncrona. Así que cualquier out los parámetros tendrían que ser asignados antes del primer await expresión, y es muy posible que tenga que haber alguna restricción en ref parámetros para evitar que se utilicen después del primer await expresión de todos modos, ya que después de eso puede que ni siquiera sean válidos.

Considere llamar a un método asíncrono con out y ref parámetros, usando variables locales para los argumentos:

int x;
int y = 10;
FooAsync(out x, ref y);

Después de FooAsync regresa, el método en sí podría regresar, por lo que esas variables locales ya no existirían lógicamente ... pero el método asíncrono aún podría usarlas en sus continuaciones. Grandes problemas. El compilador podría crear una nueva clase para capturar la variable de la misma manera que lo hace con las expresiones lambda, pero eso causaría otros problemas... aparte de cualquier otra cosa, podría tener un local cambio de variable en puntos arbitrarios a través de un método, cuando las continuaciones se ejecutan en un subproceso diferente. Extraño por decir lo menos.

Básicamente, no tiene sentido usar out y ref parámetros para async métodos, debido al tiempo involucrado. En su lugar, utilice un tipo de devolución que incluya todos los datos que le interesen.

Si solo te interesa el out y ref cambios de parámetros antes del primer await expresión, siempre puede dividir el método en dos:

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!
{
}

EDITAR:Sería factible tener out parámetros usando Task<T> y asigne el valor directamente dentro del método al igual que los valores de retorno. Sin embargo, sería un poco extraño y no funcionaría para ref parámetros.


C# está compilado en CIL y CIL no admite esto.

CIL no tiene async de forma nativa async los métodos se compilan en una clase, y todos los parámetros (usados) y las variables locales se almacenan en campos de clase, de modo que cuando se llama a un método específico de esa clase, el código sabe dónde seguir ejecutándose y qué valores tienen las variables.

ref y out los parámetros se implementan mediante punteros administrados y los campos de clase de tipo de puntero administrado no están permitidos, por lo que el compilador no puede conservar la referencia pasada.

Esta restricción en los punteros administrados en los campos de clase evita algunos códigos sin sentido, como se explica en la respuesta de Jon Skeet, ya que un puntero administrado en un campo de clase puede referirse a una variable local de una función que ya ha regresado. Sin embargo, esta restricción es tan estricta que incluso se rechaza el uso seguro y correcto. El ref /out campos podrían funcionar, si se referían a otro campo de clase, y el compilador se aseguraba de ajustar siempre las variables locales pasadas con ref /out en una clase (como si ya supiera cómo hacerlo).

Por lo tanto, C# simplemente no tiene forma de sortear las restricciones impuestas por CIL. Incluso si los diseñadores de C# quieren permitirlo (no digo que lo hagan), no pueden.