2015-01-12 14 views
7

Zrzut ekranu przedstawia go w dużym stopniu. Mam przeciążenia, jak widać na zrzucie ekranu. Używając łańcucha jako drugiego parametru, kompilator powinien zorientować się, że pierwszym argumentem może być tylko Func, a nie wyrażenie. Ale kompilator zgłasza błąd: "Wyrażenie lamda z treścią instrukcji nie może zostać przekonwertowane na drzewo wyrażeń".Błąd kompilatora dla przeciążenia Expression/Func

Dlaczego kompilator nie może odczytać prawidłowego przeciążenia?

Jawne rzucanie nie pomaga. To, co działa, gdy robię lokalną zmienną typu Func, a następnie użyj tego zamiast tego.

Ramy stosowany jest FakeItEasy 1.24.0

Wtf?

EDIT:

Oto kod, który pokazuje zachowanie:

public static void Main(string[] args) 
    { 
     //compiler error 
     A.CallTo(() => Main(A<string[]>.That.Matches(strings => 
                { 
                 return true; 
                }, "description"))); 

     //compiles 
     Func<string[], bool> predicate = strings => 
         { 
          return true; 
         }; 
     A.CallTo(() => Main(A<string[]>.That.Matches(predicate, "description"))); 

     Console.ReadLine(); 
    } 
+4

czy możesz opublikować kod, nie zrzut ekranu? – mybirthname

+2

Nie powinieneś używać 'return' w ciele lambda z wyrażeniem .....' string => true' jest wystarczające. – leppie

+1

@leppie: poprawne, nie o to jednak chodzi. Jak widać na zrzucie ekranu, kompilator powinien używać przeciążenia z Func i dlatego treść metody powinna być w porządku. Zamiast tego kompilator podaje błąd. Pytanie brzmi: dlaczego? – cmart

Odpowiedz

6

problem nie został w połączenie z Matches. Jest to wywołanie CallTo, które oczekuje na Expression<Action>.

Najwyraźniej nie tylko nie może być wyrażeniem lambda z ciałem instrukcji, ale nie może również zawierać wyrażenia lambda z ciałem instrukcji.

(nie jestem pewien, czy twój „umieścić lambda w zmiennej lokalnej” rozwiązanie praca lub czy to tylko sztuczki kompilator i nie powiedzie się w czasie wykonywania.)

Oto test ułożyła :

static void Overloaded(Action a, string param) { } 
static void Overloaded(Expression<Action> e) { } 

static void CallToAction(Action a) { } 
static void CallToExprAc(Expression<Action> a) { } 

static void Main(string[] args) 
{ 
    // Works 
    CallToAction(() => Overloaded(() => { int i = 5; }, "hi")); 

    // Doesn't work - using the Expression overload 
    CallToAction(() => Overloaded(() => { int i = 5; })); 

    // Doesn't work - wrapped in an outer Expression 
    CallToExprAc(() => Overloaded(() => { int i = 5; }, "hi")); 
} 

Niezależnie, czy „umieścić lambda wyrażenie zabudowanych w lokalnym” działa zależy jak FakeItEasy jest realizowany. Podejrzewam, że zadziała tutaj, ale coś podobnego w np. LINQ-SQL nie byłoby - po prostu zawiedzie w czasie wykonywania, a nie w czasie kompilacji.

Nie jestem pewien, czy jest to błąd kompilatora, błąd specyfikacji czy pożądane zachowanie. W sekcji 6.5 specyfikacji C# mamy

Niektórych wyrażeń lambda nie można przekonwertować na typy drzewek wyrażeń: nawet jeśli konwersja istnieje, to kończy się niepowodzeniem podczas kompilacji. Tak jest w przypadku, gdy wyrażenie lambda:

• posiada korpus bloku

• Zawiera proste lub złożone operatory przypisania

• Zawiera dynamicznie Bound wyraz

• Czy asynchroniczny

który nie mówi "zawiera wyrażenie lambda, którego nie można przekonwertować na drzewo wyrażeń pe ".

+0

Ahh .. Dobra uwaga! I tak, działa również w środowisku wykonawczym, gdy tworzysz zmienną lokalną. Thx! – cmart

+0

@MarChr Cieszę się, że to słyszę, i dobre miejsce - z pewnością ciekawy problem, na który warto zwrócić uwagę. – Rawling

+0

Tak, ale teraz ma to sens. Dziękuję Ci! – cmart

Powiązane problemy