_ => Was bedeutet dieser Unterstrich in Lambda-Ausdrücken?


111

Was bedeutet ein Lambda-Ausdruck _=> expr?

Was ist der Zweck _als Input für Lambda?

Beispiel:

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

8
Hallo und willkommen bei StackOverflow. Ich habe mir erlaubt, Ihre Frage leicht zu bearbeiten, um Ihre Chance auf nützliche Antworten zu erhöhen. Ich hoffe, es macht Ihnen nichts aus.
Lasse V. Karlsen

Beachten Sie, dass unter der Annahme , listein IEnumerable<T>, sie könnten (und sollten) haben gerade verwendetsum = list.Count();
BlueRaja - Danny Pflughoeft

Ich denke, dies kann verwendet werden, um zu verhindern, dass Sie den Bereich mit einem neuen Variablennamen "verschmutzen", der möglicherweise an einer anderen Stelle verwendet wird, die einen Konflikt verursachen würde.
Tim Schmelter

Antworten:


83

Dies ist eine Konvention, die verwendet wird, wenn Sie sich nicht für den Parameter interessieren.


3
Es ist häufiger in Haskell und anderen funktionalen Sprachen. Ich denke, da kommt es her.
Gabe Moothart

10
In Haskell ist ML, Scala und andere _das Platzhalterzeichen beim Mustervergleich. Es bedeutet im Grunde "Es ist mir egal, ich möchte immer, dass dies übereinstimmt". Dieses "Es ist mir egal" wird dann übertragen, wenn es darum geht, Dinge zu benennen , die Sie nicht interessieren, und von dort geht es in andere Programmiersprachen über. Es wird zum Beispiel auch in Ruby verwendet, um dasselbe wie in diesem Beispiel zu bedeuten, obwohl _es in Ruby absolut keine besondere Bedeutung hat.
Jörg W Mittag

@ JörgWMittag True im Mai 2010, aber nicht ab Juni 2010. Super Timing! :) stackoverflow.com/q/6397078/38765
Andrew Grimm

38

Es ist ein Parametername, wenn auch nicht nützlich, aber es ist die einzige , normalerweise verwendet (von einigen Konventionen) , wenn Sie angeben müssen , dass der Ausdruck hat einen Parameter , um den Code zu kompilieren zu bekommen, aber Sie nicht wirklich Pflege darüber, also wirst du es einfach ignorieren.

Grundsätzlich wird die Syntax für das verwendet, was eine legale Kennung in C # ausmacht. Da eine Kennung mit einem Unterstrich beginnen kann und nichts anderes enthält, handelt es sich lediglich um einen Parameternamen.

Sie hätten einfach schreiben können:

var _ = 10;

1
Können wir anstelle von _ () verwenden?
Amesh

2
Hast du versucht, das zu benutzen?
Lasse V. Karlsen

Ja, ich hatte es verwendet, als ich einen Thread mit Lambda-Ausdruck erstellt habe. Thread t= new Thread(()=>doSomething(x,y)); t.start();
Amesh

Ich gehe davon aus, dass bei der Verwendung von _ jede Variable der Sammlung an den Lambda-Ausdruck übergeben wird, obwohl sie nicht verwendet wird. Aber wenn wir () verwenden, kann es nicht passieren. Ich meine Parameter weniger Lambda.
Amesh

Sie müssen es mit dem ForEach-Methodenaufruf versuchen. Der Thread-Konstruktor ist überlastet und nimmt einen Delegaten auf, der keine Parameter akzeptiert. Versuchen Sie, eine Methode wie ForEach aufzurufen, die einen Delegaten verwendet, der stattdessen einen Parameter verwendet.
Lasse V. Karlsen


10

Da der Lamda-Ausdruck meistens in einem kurzen, anonymen Code verwendet wird, so dass der Name der Variablen manchmal nicht erforderlich ist, verwenden sie die Variable im Codeblock nicht, sodass sie nur ein _ für eine kurze Konvention angeben


7

Ich unterstütze auch die Verwendung von _ => _.method()einzeiligen Lambdas mit Methodenaufruf, da dies das kognitive Gewicht des Befehls verringert. Insbesondere bei der Verwendung von Generika wird beim Schreiben x => x.method()nur die sekundenschnelle Überlegung "Was ist das 'x'? Ist es eine Koordinate im Raum?" Hinzugefügt.

Betrachten Sie den folgenden Fall:

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

Bei einem Generics-Aufruf fungiert der Unterstrich in diesem Fall als "Bypass-Symbol". Es vermeidet Redundanz und definiert, dass der Typ des Arguments offensichtlich ist und aus der Verwendung abgeleitet werden kann - genau wie wenn Sie 'var' verwenden, um zu verhindern, dass eine Typdeklaration wiederholt wird. Schreibenclient=>client.Init() hier würde die Anweisung nur verlängern, ohne ihr eine Bedeutung hinzuzufügen.

Dies gilt natürlich nicht für die Parameter, die an die Methode übergeben werden sollen, die beschreibend benannt werden sollte. Z.B.:Do( id=>Log(id) );

Die Verwendung eines einzelnen Unterstrichparameters für Methodenaufrufe ist kaum zu rechtfertigen, wenn ein Codeblock anstelle eines Einzeilers verwendet wird, da der Lambda-Bezeichner von seiner generischen Definition getrennt wird. Wenn derselbe Bezeichner wiederverwendet werden soll, geben Sie ihm im Allgemeinen einen beschreibenden Namen.

Das Fazit ist, dass Ausführlichkeit nur für die Disambiguierung gerechtfertigt ist, insbesondere für Lambdas, die erstellt wurden, um die Erstellung anonymer Delegierten zu vereinfachen. In jedem Fall sollte gesunder Menschenverstand verwendet werden, um Lesbarkeit und Prägnanz auszugleichen. Wenn das Symbol nur ein "Haken" für die tatsächliche Funktionalität ist, sind Bezeichner mit einem Zeichen vollkommen in Ordnung. Dies ist bei For-Schleifen und den Buchstaben "i" und "j" als Indexer der Fall.


2
+1 für diesen Ansatz! Ich dachte, ich wäre der einzige, der Unterstriche in Lambdas verwendet, um "das kognitive Gewicht zu reduzieren" und nicht um zu zeigen, dass dieser Parameter nicht verwendet wird. Mit Unterstrichen ist das Lesen einfacher, insbesondere wenn viele Verkettungen vorhanden sind und Sie sofort auf den Typ schließen können, wie dies bei LINQ-Abfragen häufig der Fall ist!
Varvara Kalinina

3
Do(id => Log(id))wird besser als abgekürzt Do(Log).
Aluan Haddad
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.