Czy wyrażenie lambda w języku C # może mieć więcej niż jedną instrukcję?

135

Czy wyrażenie lambda języka C # może zawierać więcej niż jedną instrukcję?

(Edytuj: jak wspomniano w kilku poniższych odpowiedziach, to pytanie pierwotnie dotyczyło „wierszy”, a nie „stwierdzeń”).

paseena
źródło
17
Tak, możesz użyć wielu linii. Nie czuję się dobrze, dając pełną odpowiedź.
Tesserex
1
@Tesserex - co by nie było odpowiedzią ... masz rację!
RQDQ
3
@RQDQ Ponieważ jest to pytanie tak lub nie, nie czuję, że jest godny reputacji, którą wygenerowałby na podstawie głosów poparcia.
Tesserex

Odpowiedzi:

200

Pewnie:

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
źródło
32

(Zakładam, że naprawdę mówisz o wielu instrukcjach, a nie o wielu wierszach).

Możesz użyć wielu instrukcji w wyrażeniu lambda przy użyciu nawiasów klamrowych, ale tylko składnię, która nie używa nawiasów klamrowych, można przekształcić w drzewo wyrażeń:

// 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
źródło
1
Próbuję zrozumieć, dlaczego Func zezwala na nawiasy klamrowe, a Wyrażenie nie pozwala. W każdym razie Expression będzie zgodne z Func, czy istnieje sposób, aby dodać logikę wielu wierszy do drzewa wyrażeń? Jeśli nie, dlaczego istnieją ograniczenia?
Habeeb
8
@Habeeb: "Anyway Expression będzie zgodne z Func" Nie zawsze. W większości przypadków w ogóle nie jest kompilowany do delegata - po prostu sprawdzany jako dane. Drzewa wyrażeń w .NET 4.0 zyskały możliwość dołączania wielu instrukcji za pośrednictwem Expression.Block, ale język C # tego nie obsługuje. Mógłby, ale wymagałoby to więcej prac projektowych / wdrożeniowych / testowych.
Jon Skeet,
26

W wyrażeniu lambda możesz umieścić dowolną liczbę nowych linii; C # ignoruje znaki nowej linii.

Prawdopodobnie chciałeś zapytać o wiele stwierdzeń .

Wiele instrukcji może być umieszczonych w nawiasach klamrowych.

Zobacz dokumentację .

SLaks
źródło
17
Czy nie byłoby dokładniejsze stwierdzenie, że C # traktuje jednakowo wszystkie białe znaki, w tym znaki nowej linii? Stwierdzenie, że ignoruje znaki nowej linii, brzmi trochę myląco - sprawia wrażenie, jakby po prostu je całkowicie usuwał i można podzielić słowo kluczowe na nową linię lub coś w tym stylu.
Tesserex
7

Od C # 7:

Instrukcja jednowierszowa:

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

Oświadczenie wielowierszowe:

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

chociaż są to nazywane funkcjami lokalnymi, wydaje mi się, że wygląda to nieco czyściej niż poniższe i faktycznie jest takie samo

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; };
BigChief
źródło
4
Func<string, bool> test = (name) => 
{
   if (name == "yes") return true;
   else return false;
}
Ustrój
źródło
5
Func <string, bool> test = name => name == "yes";
asawyer
3
Polity demonstruje wielowierszowy format, o który prosi pytanie, a nie zabawne sugestie dotyczące golfa. Wdrożenie mądrego kodu oznaczałoby, że nie jest to odpowiedź!
Caius Jard
0

Z c # 7.0 możesz również używać w ten sposób

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
źródło
0

Powiedzmy, że masz klasę:

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

Dzięki C # 7.0 w tej klasie możesz to zrobić nawet bez nawiasów klamrowych:

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

i

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

byłby taki sam jak:

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

Może to być również pomocne, jeśli chcesz napisać zwykłą metodę lub konstruktor w jednym wierszu lub gdy potrzebujesz więcej niż jednej instrukcji / wyrażenia do spakowania w jedno wyrażenie:

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

lub

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

lub

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

Więcej o dekonstrukcji krotek w dokumentacji .

Konard
źródło