Errores y advertencias al usar expresiones lambda y funciones anónimas

Hay varios errores relacionados con la declaración y el uso de expresiones lambda:

  • CS0748: uso incoherente del parámetro lambda. Los tipos de parámetro deben ser todos explícitos o todos implícitos.
  • CS1621: la instrucción yield no se puede usar dentro de un método anónimo o una expresión lambda.
  • CS1628: no se pueden usar los parámetros inref o out dentro de un método anónimo, una expresión lambda o una expresión de consulta.
  • CS1632: El control no puede abandonar el cuerpo de un método anónimo o de una expresión lambda.
  • CS1673: los métodos anónimos, las expresiones lambda y las expresiones de consulta incluidos en estructuras no pueden tener acceso a miembros de instancia de "this".
  • CS1686: No puede tomarse la dirección de la variable local o sus miembros y usarse en un método anónimo o una expresión lambda.
  • CS1706: la expresión no puede contener métodos anónimos ni expresiones lambda.
  • CS8030: una función anónima convertida en un delegado que devuelve void no puede devolver un valor.
  • CS8175: No se puede usar la variable local de tipo ref dentro de un método anónimo, una expresión lambda o una expresión de consulta.
  • CS8916: los atributos de expresiones lambda requieren una lista de parámetros entre paréntesis.
  • CS8971: el argumento InterpolatedStringHandlerArgument no tiene ningún efecto cuando se aplica a parámetros lambda y se omitirá en el sitio de llamada.
  • CS8975: la palabra clave contextual var no se puede usar como un tipo de valor devuelto lambda explícito.
  • CS9098: el parámetro lambda con tipo implícito "..." no puede tener un valor predeterminado.

Además, hay varias advertencias relacionadas con la declaración y el uso de expresiones lambda:

  • CS8971: el argumento InterpolatedStringHandlerArgument no tiene ningún efecto cuando se aplica a parámetros lambda y se omitirá en el sitio de llamada.
  • CS9099: el valor del parámetro predeterminado no coincide en el tipo delegado de destino.
  • CS9100: el parámetro tiene modificador de parámetros en lambda, pero no en el tipo delegado de destino.

Limitaciones de sintaxis en expresiones lambda

Alguna sintaxis de C# está prohibida en expresiones lambda y métodos anónimos. El uso de construcciones no válidas en una expresión lambda genera los siguientes errores:

  • CS1621: La instrucción yield no se puede usar dentro de un método anónimo o una expresión lambda.
  • CS1628: No se pueden usar los parámetros in, ref o out dentro de un método anónimo, una expresión lambda o una expresión de consulta.
  • CS1632: El control no puede abandonar el cuerpo de un método anónimo o de una expresión lambda.
  • CS1673: Los métodos anónimos, las expresiones lambda y las expresiones de consulta incluidos en estructuras no pueden tener acceso a miembros de instancia de this.
  • CS1686: No puede tomarse la dirección de la variable local o sus miembros y usarse en un método anónimo o una expresión lambda.
  • CS8175: No se puede usar la variable local de tipo ref dentro de un método anónimo, una expresión lambda o una expresión de consulta.

No se permiten todas las construcciones siguientes en expresiones lambda:

  • Instrucciones yield (yield return o yield break)
  • Llamada a un método que tiene un parámetro in, ref o out
  • Variables locales ref
  • Instrucciones break, goto y continue
  • Acceso a this cuando this es un tipo struct
  • Métodos anónimos o expresiones lambda dentro de otra expresión, como un constructor de atributos.

No se puede usar ninguna de estas construcciones en una expresión lambda ni en un método anónimo. Se admiten muchas en una función local.

Además, los tipos de controlador de cadenas interpoladas se ignoran cuando se aplican a un parámetro lambda. Si usa alguno, verá la advertencia siguiente:

  • CS8971: el argumento InterpolatedStringHandlerArgument no tiene ningún efecto cuando se aplica a parámetros lambda y se omitirá en el sitio de llamada.

Devoluciones y parámetros de expresiones lambda

Estos errores indican un problema con una declaración de parámetro:

  • CS0748: uso incoherente del parámetro lambda. Los tipos de parámetro deben ser todos explícitos o todos implícitos.
  • CS9098: el parámetro lambda con tipo implícito "..." no puede tener un valor predeterminado.
  • CS8030: una función anónima convertida en un delegado que devuelve void no puede devolver un valor.
  • CS8916: los atributos de expresiones lambdavrequieren una lista de parámetros entre paréntesis.
  • CS8975: la palabra clave contextual "var" no se puede usar como un tipo de valor devuelto lambda explícito.

Los parámetros de expresión lambda deben seguir estas reglas:

  • Cuando una expresión lambda tiene varios parámetros, todos ellos deben escribirse explícitamente o todos deben escribirse implícitamente.
  • Todos los parámetros lambda con un valor predeterminado deben escribirse explícitamente.
  • Si los atributos se aplican a cualquier parámetro, la lista de parámetros debe ir entre paréntesis.

Los tipos devueltos de expresión lambda deben seguir estas reglas:

  • Una expresión lambda que devuelve cualquier valor no se puede convertir en un delegado devuelto void, como Action.
  • El tipo de valor devuelto se infiere, o un tipo explícito. No se permite un tipo de valor devuelto declarado mediante la palabra clave var.

Tipo de delegado de expresión lambda

  • CS9099: advertencia: el valor del parámetro predeterminado no coincide en el tipo delegado de destino.

Cuando se declara un valor predeterminado o se agrega el modificador params con un parámetro de expresión lambda, el tipo delegado no es ninguno de los tipos Func o Action. En su lugar, es un tipo personalizado que incluye el valor de parámetro predeterminado o el modificador params. El código siguiente genera advertencias porque asigna una expresión lambda que tiene un parámetro predeterminado a un tipo Action:

Action<int> a1 = (int i = 2) => { };
Action<string[]> a3 = (params string[] s) => { };

Para corregir el error, quite el parámetro predeterminado o use una variable con tipo implícito para el tipo delegado:

Action<int> a1 = (int i) => { };
var a2 = (int i = 2) => { };
Action<string[]> a3 = (string[] s) => { };
var a4 = (params string[] s) => { };