Kann ein C # -Lambda-Ausdruck mehr als eine Anweisung haben?

131

Kann ein C # -Lambda-Ausdruck mehr als eine Anweisung enthalten?

(Bearbeiten: Wie in mehreren der folgenden Antworten erwähnt, wurde diese Frage ursprünglich eher nach "Zeilen" als nach "Aussagen" gestellt.)

paseena
quelle
17
Ja, Sie können mehrere Zeilen verwenden. Ich fühle mich nicht richtig, wenn ich eine vollständige Antwort mache.
Tesserex
1
@Tesserex - was macht es nicht zu einer Antwort ... du hast recht!
RQDQ
3
@RQDQ Da es sich um eine Ja- oder Nein-Frage handelt, habe ich nicht das Gefühl, dass sie der Wiederholung würdig ist, die sie aus Upvotes generieren würde.
Tesserex

Antworten:

195

Sicher:

List<String> items = new List<string>();

var results = items.Where(i => 
            {
                bool result;

                if (i == "THIS")
                    result = true;
                else if (i == "THAT")
                    result = true;
                else
                    result = false;

                return result;
            }
        );
RQDQ
quelle
31

(Ich gehe davon aus, dass Sie wirklich über mehrere Aussagen und nicht über mehrere Zeilen sprechen.)

Sie können mehrere Anweisungen in einem Lambda-Ausdruck mit geschweiften Klammern verwenden, aber nur die Syntax, die keine geschweiften Klammern verwendet, kann in einen Ausdrucksbaum konvertiert werden:

// Valid
Func<int, int> a = x => x + 1;
Func<int, int> b = x => { return x + 1; };        
Expression<Func<int, int>> c = x => x + 1;

// Invalid
Expression<Func<int, int>> d = x => { return x + 1; };
Jon Skeet
quelle
1
Ich versuche zu verstehen, warum Func Klammern zulässt und Expression nicht zulässt. Wie auch immer, Ausdruck wird als Funktion erfüllt. Gibt es eine Möglichkeit, dem Ausdrucksbaum eine mehrzeilige Logik hinzuzufügen? Wenn nein, warum gibt es Einschränkungen?
Habeeb
8
@Habeeb: "Wie auch immer, Ausdruck wird als Func erfüllt" Nicht immer. Die meiste Zeit wird es nie an einen Delegierten kompiliert - nur als Daten untersucht. Ausdrucksbäume in .NET 4.0 haben die Möglichkeit erhalten, mehrere Anweisungen über Expression.Block einzuschließen, aber die C # -Sprache unterstützt dies nicht. Es könnte, aber das würde mehr Design / Implementierung / Testarbeit erfordern.
Jon Skeet
26

Sie können so viele Zeilenumbrüche in einen Lambda-Ausdruck einfügen, wie Sie möchten. C # ignoriert Zeilenumbrüche.

Sie wollten wahrscheinlich nach mehreren Aussagen fragen .

Mehrere Anweisungen können in geschweifte Klammern gesetzt werden.

Siehe die Dokumentation .

SLaks
quelle
17
Wäre es nicht genauer zu sagen, dass C # alle Leerzeichen, einschließlich Zeilenumbrüche, gleich behandelt? Es klingt etwas irreführend zu sagen, dass Zeilenumbrüche ignoriert werden - es sieht so aus, als würden sie nur vollständig entfernt, und Sie könnten ein Schlüsselwort auf eine neue Zeile oder etwas anderes aufteilen.
Tesserex
6

Seit C # 7:

Einzeilige Anweisung:

int expr(int x, int y) => x + y + 1; 

Mehrzeilige Anweisung:

int expr(int x, int y) { int z = 8; return x + y + z + 1; };

Obwohl diese als lokale Funktionen bezeichnet werden, denke ich, dass dies ein bisschen sauberer aussieht als die folgenden und praktisch gleich ist

Func<int, int, int> a = (x, y) => x + y + 1;

Func<int, int, int> b = (x, y) => { int z = 8; return x + y + z + 1; };
Großer Chef
quelle
4
Func<string, bool> test = (name) => 
{
   if (name == "yes") return true;
   else return false;
}
Gemeinwesen
quelle
5
Func <string, bool> test = name => name == "yes";
Asawyer
3
Polity demonstriert das von der Frage geforderte Mehrzeilenformat und unterhält keine Vorschläge zum Golfen. Um Ihren weisen Code zu implementieren, wäre dies "keine Antwort"!
Caius Jard
3

Aus Lambda-Ausdrücken (C # -Programmierhandbuch) :

Der Hauptteil einer Lambda-Anweisung kann aus einer beliebigen Anzahl von Anweisungen bestehen. In der Praxis gibt es jedoch normalerweise nicht mehr als zwei oder drei.

jfs
quelle
0

Mit c # 7.0 können Sie auch so verwenden

Public string ParentMethod(int i, int x){
    int calculation = (i*x);
    (string info, int result) InternalTuppleMethod(param1, param2)
    {
        var sum = (calculation + 5);
        return ("The calculation is", sum);
    }
}
Jigar Prajapati
quelle
0

Angenommen, Sie haben eine Klasse:

    public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
    }

Mit dem C # 7.0 in dieser Klasse können Sie dies auch ohne geschweifte Klammern tun:

Action<int, int> action = (x, y) => (_, _) = (X += x, Y += y);

und

Action<int, int> action = (x, y) => _ = (X += x, Y += y);

wäre das gleiche wie:

Action<int, int> action = (x, y) => { X += x; Y += y; };

Dies kann auch hilfreich sein, wenn Sie eine reguläre Methode oder einen Konstruktor in eine Zeile schreiben müssen oder wenn Sie mehr als eine Anweisung / einen Ausdruck benötigen, um in einen Ausdruck gepackt zu werden:

public void Action(int x, int y) => (_, _) = (X += x, Y += y);

oder

public void Action(int x, int y) => _ = (X += x, Y += y);

oder

public void Action(int x, int y) => (X, Y) = (X + x, Y + y);

Mehr zur Dekonstruktion von Tupeln in der Dokumentation .

Konard
quelle