2010-05-06 16 views
77

¿Qué significa una expresión lambda como _=> expr?_ => ¿Qué significa esto en las expresiones Lambda?

¿Cuál es el propósito de _ como entrada para lambda?

Ejemplo:

int sum = 0; 
list.ForEach(_=> { sum += 1; }); 
+5

Hola y bienvenidos a StackOverflow.Me tomé la libertad de editar tu pregunta ligeramente para aumentar tus posibilidades de obtener respuestas útiles, espero que no te importe. –

+0

Tenga en cuenta que, suponiendo 'list' es un' IEnumerable ', podrían * (y deberían) * haber utilizado' sum = list.Count(); ' –

Respuesta

58

Eso es una convención utilizada cuando no se preocupan por el parámetro.

+1

Es una convención * a *, y no una utilizada por todos. – Bevan

+3

Es más común en Haskell y otros lenguajes funcionales. Creo que de ahí viene. –

+7

En Haskell, ML, Scala y otros, '_' es el carácter comodín en la coincidencia de patrones. Básicamente significa "No me importa, yo * siempre * quiero que coincida". Este "no me importa" se lleva a cabo cuando se trata de * nombrar * cosas que no te importan y, a partir de ahí, se extiende a otros lenguajes de programación. Por ejemplo, también se usa en Ruby para significar lo mismo que en este ejemplo, aunque '_' no tiene ningún significado especial en Ruby. –

22

_ es un nombre de variable válido. Solo están usando _ como variable.

35

Es un nombre de parámetro, aunque no una útil, pero es la que se utiliza normalmente (por algunas convenciones) cuando es necesario especificar que la expresión tiene un parámetro con el fin de obtener el código para compilar, pero realmente no te importa, así que simplemente lo ignorarás.

Básicamente explotando la sintaxis para lo que constituye un identificador legal en C#, y dado que un identificador puede comenzar con un guión bajo, y no contener nada más, es solo un nombre de parámetro.

Se podía haber fácilmente haber escrito:

var _ = 10; 
+1

En lugar de _, ¿podemos usar()? – amesh

+2

¿Has intentado usar eso? –

+0

Sí, lo había usado cuando estaba creando un hilo usando la expresión lambda. 'Thread t = new Thread (() => doSomething (x, y)); t.start(); ' – amesh

9

Dado que la expresión lambda se utiliza sobre todo en un código corto, anónima para que el nombre de la variable a veces no es lo necesite, incluso ellos no utilizan la variable en el bloque de código, por lo que simplemente dan un _ para abreviar, convención

3

También utilizo el _ => _.method() para una sola línea, call-call lambdas, ya que reduce el peso cognitivo de la instrucción. Especialmente cuando se usan genéricos, escribir x => x.method() solo agrega la consideración de "¿Qué es esta 'x'? ¿Es una coordenada en el espacio?".

Considere el siguiente caso:

Initialize<Client> (_=>_.Init());

Se utiliza con una llamada Genéricos, el subrayado, en este caso funciona como un "símbolo de derivación". Evita la redundancia, ya que define que el tipo de argumento es obvio y puede inferirse del uso, al igual que cuando se usa 'var' para evitar la repetición de una declaración de tipo. Escribir client=>client.Init() aquí simplemente alargaría la instrucción sin agregarle ningún significado.

Obviamente, esto no se aplica a los parámetros que se pasarán al método, que debe denominarse descriptivamente. Ej .: Do(id=>Log(id));

El uso-subrayado-parámetro único para llamadas de método no es justificable cuando se utiliza un bloque de código en lugar de una sola línea, ya que el identificador de lambda se desconecta de su definición genéricos. En general, cuando se va a reutilizar el mismo identificador, dele un nombre descriptivo.

La conclusión es que la verbosidad es solo justificable para la desambiguación, especialmente para las lambdas, que fueron creadas para simplificar la creación anónima de delegados en primer lugar. En cualquier caso, debe usarse el sentido común, equilibrando la legibilidad y la concisión. Si el símbolo es solo un "gancho" para la funcionalidad real, los identificadores de un solo carácter están perfectamente bien. Ese es el caso con For-Loops y las letras "i" y "j" como indexadores.

+1

+1 para este enfoque! Pensé que era el único que usa guiones bajos en lambdas para "reducir el peso cognitivo" y no para mostrar que este parámetro no se usa. Se lee más fácilmente con guiones bajos, especialmente si hay mucho encadenamiento e inmediatamente se puede inferir el tipo, como suele ser el caso con las consultas LINQ. –

+0

'Do (id => Log (id))' se abrevia mejor como 'Do (Log)'. –