_ => cosa significa questo trattino basso nelle espressioni Lambda?


111

Cosa significa un'espressione lambda _=> expr?

Qual è lo scopo di _come input per lambda?

Esempio:

int count = 0;
list.ForEach(_ => count += 1);

8
Ciao e benvenuto in StackOverflow. Mi sono preso la libertà di modificare leggermente la tua domanda per aumentare le tue possibilità di ottenere risposte utili, spero non ti dispiaccia.
Lasse V. Karlsen

Nota che, supponendo che listsia un IEnumerable<T>, avrebbero potuto (e dovuto) aver appena usatosum = list.Count();
BlueRaja - Danny Pflughoeft

Immagino che questo possa essere usato per evitare di "inquinare" l'ambito con un nuovo nome di variabile che potrebbe essere utilizzato da qualche altra parte che potrebbe causare un conflitto.
Tim Schmelter

Risposte:


84

Questa è una convenzione usata quando non ti interessa il parametro.


3
È più comune in Haskell e in altri linguaggi funzionali. Penso che sia da lì che viene.
Gabe Moothart

10
In Haskell, ML, Scala e altri, _è il carattere jolly nella corrispondenza dei modelli. Fondamentalmente significa "non mi interessa, voglio sempre che corrisponda". Questo "non mi interessa" poi viene trasferito quando si tratta di nominare cose che non ti interessano e da lì si riversa in altri linguaggi di programmazione. Ad esempio, è anche usato in Ruby per significare la stessa cosa di questo esempio, anche se non _ha assolutamente alcun significato speciale in Ruby.
Jörg W Mittag

@ JörgWMittag Vero a maggio 2010, ma non a giugno 2010. Tempismo fantastico! :) stackoverflow.com/q/6397078/38765
Andrew Grimm

38

È un nome di parametro, anche se non utile, ma è quello tipicamente utilizzato (da alcune convenzioni) quando è necessario specificare che l'espressione ha un parametro per ottenere il codice da compilare, ma non ti interessa davvero a questo proposito, quindi lo ignorerai.

Fondamentalmente sfrutta la sintassi per ciò che costituisce un identificatore legale in C # e poiché un identificatore può iniziare con un carattere di sottolineatura e non contenere nient'altro, è solo un nome di parametro.

Avresti potuto facilmente scrivere:

var _ = 10;

1
Invece di _, possiamo usare ()?
amesh

2
Hai provato a usarlo?
Lasse V. Karlsen

Sì, l'ho usato quando stavo creando un thread usando l'espressione lambda. Thread t= new Thread(()=>doSomething(x,y)); t.start();
amesh

Quello che presumo è che l'uso di _ sta passando ogni variabile della raccolta all'espressione lambda anche se non viene utilizzata. Ma quando usiamo () potrebbe non accadere. Intendo parametro meno lambda.
amesh

Devi provarlo usando la chiamata al metodo ForEach. È presente un overload sul costruttore Thread che accetta un delegato che non accetta parametri. Prova a chiamare un metodo, come quello ForEach, che accetta un delegato che accetta invece un parametro.
Lasse V. Karlsen


10

Poiché l'espressione lamda viene utilizzata principalmente in un codice breve e anonimo in modo che il nome della variabile a volte non sia necessario, anche loro non usano la variabile nel blocco di codice, quindi danno solo un _ per una breve convenzione


7

Secondo anche l'uso di _ => _.method()lambda di una riga, chiamata metodo, poiché riduce il peso cognitivo dell'istruzione. Specialmente quando si usano i generici, la scrittura x => x.method()aggiunge semplicemente quella considerazione di una frazione di secondo di "Cos'è questa 'x'? È una coordinata nello spazio?".

Considera il seguente caso:

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

Utilizzato con una chiamata Generics, il carattere di sottolineatura in questo caso funziona come un "simbolo di esclusione". Evita la ridondanza, definendo che il tipo dell'argomento è ovvio e può essere dedotto dall'uso, proprio come quando si usa "var" per evitare di ripetere una dichiarazione di tipo. Scrivere client=>client.Init()qui renderebbe semplicemente più lunga l'istruzione senza aggiungervi alcun significato.

Ovviamente, questo non si applica ai parametri da passare al metodo, che dovrebbe essere denominato in modo descrittivo. Per esempio.:Do( id=>Log(id) );

L'utilizzo di un singolo carattere di sottolineatura per le chiamate ai metodi è difficilmente giustificabile quando si utilizza un blocco di codice invece di una riga, poiché l'identificatore lambda viene disconnesso dalla sua definizione generica. In generale, quando lo stesso identificatore deve essere riutilizzato, dagli un nome descrittivo.

La linea di fondo è che la verbosità è giustificabile solo per la disambiguazione, specialmente per le lambda, che sono state create per semplificare la creazione di delegati anonimi in primo luogo. In ogni caso, dovrebbe essere usato il buon senso, bilanciando leggibilità e concisione. Se il simbolo è solo un "aggancio" alla funzionalità reale, gli identificatori di un carattere vanno benissimo. Questo è il caso dei cicli For e delle lettere "i" e "j" come indicizzatori.


2
+1 per questo approccio! Pensavo di essere stato l'unico a usare i trattini bassi nelle lambda per "ridurre il peso cognitivo" e non per dimostrare che questo parametro non viene utilizzato. È più facile leggere con i trattini bassi, soprattutto se c'è molto concatenamento e puoi immediatamente dedurre il tipo, come spesso accade con le query LINQ!
Varvara Kalinina

3
Do(id => Log(id))è meglio abbreviato come Do(Log).
Aluan Haddad
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.