¿Por qué no puedes usar un parámetro ref o out en una expresión lambda?
Encontré el error hoy y encontré una solución, pero todavía tenía curiosidad por qué esto es un error en tiempo de compilación.
CS1628 : No se puede usar el parámetro 'parámetro' ref o out dentro de un método anónimo, expresión lambda o expresión de consulta
Aquí hay un ejemplo simple:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
Respuestas:
Las lambdas tienen la apariencia de cambiar la vida útil de las variables que capturan. Por ejemplo, la siguiente expresión lambda hace que el parámetro p1 viva más tiempo que el marco del método actual ya que se puede acceder a su valor una vez que el marco del método ya no está en la pila
Otra propiedad de las variables capturadas es que los cambios en la variable también son visibles fuera de la expresión lambda. Por ejemplo, las siguientes impresiones 42
Estas dos propiedades producen un cierto conjunto de efectos que se enfrentan a un parámetro de referencia de las siguientes maneras
Estas son propiedades algo incompatibles y son una de las razones por las que no están permitidas en las expresiones lambda.
fuente
ref
dentro de la expresión lambda, pero el deseo de usarlo no ha sido alimentado.Bajo el capó, el método anónimo se implementa al izar variables capturadas (que es de lo que se trata su cuerpo de preguntas) y almacenarlas como campos de una clase generada por el compilador. No hay forma de almacenar un parámetro
ref
oout
como un campo. Eric Lippert lo discutió en una entrada de blog . Tenga en cuenta que existe una diferencia entre las variables capturadas y los parámetros lambda. Usted puede tener "parámetros formales" como el siguiente, ya que son variables no capturados:fuente
Puede, pero debe definir explícitamente todos los tipos para
Sin embargo, es inválido
Es válido
fuente
ref
oout
, dentro de una lambda. Está claro si lee el código de ejemplo (intente leerlo nuevamente). La respuesta aceptada explica claramente por qué. Su respuesta es sobre el usoref
oout
parámetro de la lambda. Totalmente sin responder la pregunta y hablando de otra cosaComo este es uno de los mejores resultados para "C # lambda ref" en Google; Siento que necesito ampliar las respuestas anteriores. La sintaxis de delegado anónimo más antigua (C # 2.0) funciona y admite firmas más complejas (así como cierres). Los delegados anónimos y de Lambda, como mínimo, han compartido la implementación percibida en el backend del compilador (si no son idénticos), y lo más importante, apoyan los cierres.
Lo que estaba tratando de hacer cuando hice la búsqueda, para demostrar la sintaxis:
Solo tenga en cuenta que Lambdas es más seguro desde el punto de vista matemático y de procedimiento (debido a la promoción del valor de referencia mencionado anteriormente): puede abrir una lata de gusanos. Piensa cuidadosamente cuando uses esta sintaxis.
fuente
(a, b, c, ref d) => {...}
yref
estaba subrayado en rojo con el mensaje de error "El parámetro '4' debe declararse con la palabra clave 'ref'". Facepalm! PD: ¿qué es "promoción de valor de referencia"?Y tal vez esto?
fuente