2012-05-10 2 views
25

Ho usato espressioni lambda in altre lingue prima di usarle in C#, e così ho preso l'abitudine di usare _ per lambdas semplici sotto forma di Func<T, TResult>, specialmente per lambdas semplici dove il corpo è solo un'espressione che rappresenta il valore di ritorno (predicati, ecc.). Tuttavia, in C# spesso vedo singole lettere utilizzate al posto di _ per questi stessi tipi di espressioni lambda, come ad esempio x,y,z,i,j,k. L'approccio alla lettera mi sembra strano, poiché quelle lettere hanno già un altro significato tipico nell'uso comune, per le variabili del ciclo. _ è spesso più facile da leggere secondo me. Lo stile a singola lettera è davvero lo stile stabilito per lambda in C#?Stile C#: Lambdas, _ => o x =>?

Esempi:

quello che sono abituato a scrivere:

var ages = people.Select(_ => _.Age); 

quello che sto vedendo in fase di scrittura, invece:

var ages = people.Select(x => x.Age); // choice of 'x' is not consistent 
+24

non ho mai visto una sottolineatura in uso. –

+0

Personalmente uso 'w' per il parametro lambda quando è banale capire di cosa sto parlando. Resti di http://research.microsoft.com/en-us/um/cambridge/projects/comega/ – Blindy

+1

Solo persone innamorate di terse, personalmente uso un nome significativo. né x né _ sono significativi. l'età sarebbe stata la mia scelta nel tuo esempio. –

risposta

46

Molti sviluppatori C# utilizzano _ per indicare che il parametro non verrà utilizzato e una lettera o un altro nome breve quando viene utilizzato il parametro .

Altre risorse:

+1

upvote per l'articolo di Charlie Flowers che spiega l'avvento dell'uso legittimo _. –

+1

I miei esempi non erano corretti (avrei dovuto usare p o person in quegli esempi). All'inizio ho pensato che potesse essere applicato solo ai casi in cui il tipo di _ era generico/sconosciuto, ma in tutti i casi in cui _ è usato, almeno qualcosa deve essere conosciuto sul tipo a meno che non si stiano utilizzando metodi su Object (nel qual caso useresti obj o simili), in modo che la giustificazione non voli. Questo chiarisce le cose un po '. –

+0

non ha mai considerato l'utilizzo di '_' per i parametri inutilizzati. ora probabilmente lo farò ovunque .. –

0

non c'è stile 'stabilita' per denominare le variabili lambda. Tuttavia, un carattere di sottolineatura in genere indica un tipo di variabile membro di istanza, il che significa che il tuo stile potrebbe entrare in conflitto con altri standard di denominazione rispetto a un nome di variabile normale.

Long Story Short - Fai ciò che funziona per te.

5

Oppure è possibile utilizzare un nome significativo, ad es.

var ages = people.Select(person => person.Age); 
+0

Sei corretto. I miei esempi avrebbero dovuto usare la persona. –

22

Si tratta di un nome di variabile, quindi mi piacerebbe andare con l'idea che il nome dovrebbe trasmettere le informazioni di cui ha bisogno per trasmettere. Quali informazioni trasmettono _?

Allo stesso fine, quali informazioni trasmettono x?

potrei scrivere il vostro esempio come questo:

var ages = people.Select(p => p.Age); 

L'idea è che ritengo che il p almeno suggerisce nel contesto di tutta la dichiarazione che si tratta di un record people. Si potrebbe prendere ancora di più:

var ages = people.Select(person => person.Age); 

Ora che trasmette al lettore che cosa è in realtà quella variabile. Naturalmente, per una dichiarazione così piccola, si può sostenere che è eccessivo. Io non la penso così, ma è una questione di preferenza. (E non solo le tue preferenze, ma la preferenza di chiunque debba supportare questo codice.)

Per espressioni lambda significativamente più grandi, multilinea e complesse, il nome diventa ancora più importante.Quanto più lontano è dal contesto di ciò che significa la variabile, tanto più il nome della variabile deve portare con sé quel contesto.

+6

Ovviamente, il caso del parametro scartato (ad esempio, per un gestore di eventi anonimo) dove stai scrivendo (_, __) => {notificationEventHandler();} è quello in cui continuo a vedere (e supporto) l'uso di nomi solo underscore. –

+1

@TetsujinnoOni: certo.In tal caso, la variabile è una variabile. L'unica informazione che deve trasmettere è "Io non sono niente, non usare me". – David

+0

In secondo luogo l'uso di '_ => _.method()' per un lambdas a una riga, chiamata metodo, poiché riduce il peso cognitivo dell'istruzione. Specialmente quando si usano i generici, scrivendo 'x => x.method()' aggiunge solo una considerazione di due secondi di "Cos'è questa 'x'? È una coordinata nello spazio?". Si consideri il seguente caso: 'Inizializzare (_ => _ Init().);' Usato con i generici, il carattere di sottolineatura in questo caso funziona come un "simbolo di bypass". Evita la ridondanza, definendo che il tipo di argomento è ovvio e può essere dedotto dall'utilizzo, proprio come quando si utilizza 'var' per impedire la ripetizione di una dichiarazione di tipo. – MaDDoX

0

C'è un motivo per cui si può dare un nome - perché a volte si può avere più ingressi e la necessità di differenziarli:

Func<int,int,int> product = (num1, num2) => (num1 * num2); // takes in two ints, and returns one int 
int x = product(2, 3); 
+0

Vero, ma non penso che sia la domanda. –

+0

Allora puoi essere un vero cazzone! (_, __) => (_ * __); EDIT: k, SO naturalmente ha preso i miei caratteri di sottolineatura come marcatori in corsivo. Basta mostrare di usare caratteri di sottolineatura doppia (o più) per più input. –

+1

@ChrisSinclair, se metti i backtick attorno alla tua espressione quei caratteri speciali verranno visualizzati così come sono. –

17

Come è una funzione lambda così diverso da qualsiasi altro metodo. Se qualcuno dovesse scrivere codice con un metodo come:

public static int getAge(Person _) 
{ 
    return _.Age; 
} 

o

public static int getAge(Person x) 
{ 
    return x.Age; 
} 

Cosa vorresti dire?

A mio parere, la scelta del nome di un parametro per un lambda dovrebbe essere altrettanto significativa del parametro di qualsiasi altro metodo. Potrei fare eccezioni occasionali per una funzione di identità x => x perché in questo caso la variabile non ha bisogno di dire nulla, può davvero essere qualsiasi cosa, ma usare un underscore o una singola lettera per tutto ciò che ho in mente rende il codice molto meno leggibile. (Così tante persone apprezzano i vantaggi di LINQ/Lambdas come leggibilità, che viene sconfitta se si nascondono tutte le variabili.)

+1

Upvote per una buona prospettiva shift – hspain

+0

@TetsujinnoOni se hai visto qualcuno scrivere un metodo 'public int getAge (Person p) {return p.Age;}' cosa diresti? So che se ho visto qualcuno scrivere che direi "dovresti usare una variabile più significativa e non un'abbreviazione". Non vedo alcuna ragione per cui la stessa logica non si applica allo stesso modo a un lambda. – Servy

+1

Per i predicati semplici, la tesi è che un nome di variabile significativo offusca ciò che sta accadendo. In entrambi i casi che hai scritto, il formalismo della definizione del metodo aumenta la quantità di rumore da cui il segnale deve essere differenziato, quindi il costo della denominazione della variabile aumenta. –

1

In C#, _ viene utilizzato per le variabili di classe (attributo) e _ non viene utilizzato per le variabili locali. Quindi è bene usare un nome significativo per variabili locali e variabili di classe.

Es:

var personList = (from person in people where person.Age > 18 select person).ToList();