2009-09-16 14 views
14

Czy można włączyć przełącznik w wyrażeniu lambda? JEŚLI nie, dlaczego? Resharper wyświetla to jako błąd.Przełącznik C# w wyrażeniu lambda

+7

Czy to się kompiluje? Nie użyłbym Resharpera jako ostatniego słowa na temat prawidłowej składni. –

+0

Oczywiście, że tak nie jest, a skompilowany błąd jest taki sam, jak wynik wyświetlany przez resharper: Wyrażenie lambda z instrukcją boody nie może zostać przekierowane do drzewa wyrażeń. – Toto

+0

NB: Nie wiem, co to jest ciało oświadczenia. – Toto

Odpowiedz

21

Można w lambda bloku oświadczenie:

Action<int> action = x => 
{ 
    switch(x) 
    { 
    case 0: Console.WriteLine("0"); break; 
    default: Console.WriteLine("Not 0"); break; 
    } 
}; 

Ale nie można tego zrobić w „pojedynczym lambda wyrażenie”, więc jest nieprawidłowy:

// This won't work 
Expression<Func<int, int>> action = x => 
    switch(x) 
    { 
    case 0: return 0; 
    default: return x + 1; 
    }; 

oznacza, że ​​może to użyj przełącznika w drzewie wyrażeń (przynajmniej tak jak jest generowany przez kompilator C#, wierzę, że .NET 4.0 przynajmniej ma wsparcie dla niego w bibliotekach).

+0

tak naprawdę wydaje się, że problemem jest chcę drzewo wyrażenie. Czy jest jakaś praca lepsza niż jeśli els, jeśli o functino? – Toto

+0

Niewielka korekta (z perspektywy czasu ... jak wiele dobrego jest z perspektywy czasu :-)). Kompilator C# 4.0 nadal nie może budować "złożonych" Wyrażeń (z 'if',' while' ...), ale można je zbudować za pomocą klasy 'Expression'. Te dwie rzeczy są oddzielone.I z mniejszym opóźnieniem: OP zapytał o drzewa ekspresji. Drugim "działaniem" powinno być 'Wyrażenie >', aby pokazać, że naprawdę chciałeś mieć Drzewo Wyrażeń, a nie delegata. – xanatos

+0

@xanatos: Dzięki, edytowałem. –

2

Hmm, nie widzę powodu, dla którego to nie powinno działać. Po prostu zachowaj ostrożność używając składni której używasz

param => { 
    // Nearly any code! 
} 

delegate (param) { 
    // Nearly any code! 
} 

param => JustASingleExpression (No switches) 
5

Tak, działa, ale musisz umieścić swój kod w bloku. Przykład:

private bool DoSomething(Func<string, bool> callback) 
{ 
    return callback("FOO"); 
} 

Następnie nazwać:

DoSomething(val => 
       { 
        switch (val) 
        { 
         case "Foo": 
          return true; 

         default: 
          return false; 
        } 
       }); 
2

Sprawdziłem to zbyt :-)

[Test] 
public void SwitchInLambda() 
{ 
    TakeALambda(i => { 
     switch (i) 
     { 
      case 2: 
       return "Smurf"; 
      default: 
       return "Gnurf"; 
     } 
    }); 
} 

public void TakeALambda(Func<int, string> func) 
{ 
    System.Diagnostics.Debug.WriteLine(func(2)); 
} 

działa dobrze (wyjścia "Smurf")!

+2

Ponieważ to nie jest wyrażenie Lambda. ** Wyrażenie Lambda ** byłoby typu 'Wyrażenie >'. To jest funkcja ** Lambda **. Spróbuj zmienić parametr wejściowy TakeALambda i zobacz różnicę. – xanatos

11

w czystej Expression (.NET 3.5), najbliżej można dostać to związek warunkowy:

Expression<Func<int, string>> func = x => 
     x == 1 ? "abc" : (
     x == 2 ? "def" : (
     x == 3 ? "ghi" : 
       "jkl")); /// yes, this is ugly as sin... 

nie zabawa, zwłaszcza gdy robi się skomplikowane. Jeśli masz na myśli wyrażenie lambda z korpusem instrukcji (tylko do użytku z LINQ-Objects), a następnie wszystko jest legalne wewnątrz szelki:

Func<int, string> func = x => { 
     switch (x){ 
      case 1: return "abc"; 
      case 2: return "def"; 
      case 3: return "ghi"; 
      default: return "jkl"; 
     } 
    }; 

Oczywiście, może być w stanie zlecić pracę; na przykład LINQ-SQL pozwala zmapować skalarne UDF (w bazie danych) sposobu na danych-kontekstem (który w rzeczywistości nie jest używany) - na przykład:

var qry = from cust in ctx.Customers 
      select new {cust.Name, CustomerType = ctx.MapType(cust.TypeFlag) }; 

gdzie jest MapType UDF, który wykonuje pracę na serwerze db.

+1

Możesz pominąć nawiasy w swoim pierwszym kodzie - wynik jest * znacznie * mniej brzydki i czasami go używam. Trzeba przyznać, że trochę się przyzwyczaja, ale nie jest to z natury mniej czytelne niż równoważny blok "switch" (mniej, twierdzę). –

+0

Bez nawiasów czasami się gubię? /: etc ... ale tak, może działać bez nich ;-p –

+0

@MarcGravell Czy nie ma nic lepszego dla czystego 'Expression' w .Net 4.0? – ken2k