2013-03-29 14 views
6

Szukałem trochę informacji na temat wnioskowania o typie, ale nie mogę zastosować żadnego z rozwiązań mojego konkretnego problemu.Powiązanie typów w zagnieżdżonych funkcjach ogólnych

Dużo pracuję nad budowaniem i przekazywaniem funkcji. Wydaje mi się, że powinien być w stanie wywnioskować typ int. Jedyne, co mogę myśleć to to, że typ zwracany przez lambdę nie jest sprawdzany przez algorytm wnioskowania typu. Usunąłem niepotrzebną logikę, aby wyraźniej pokazać tę kwestię.

Func<T> Test<T>(Func<Func<T>> func) 
{ 
    return func(); 
} 

to kompiluje:

Func<int> x = Test<int>(() => 
    { 
     int i = 0; 
     return() => i; 
    }); 

ale daje to błąd „Argumenty typu dla metody nie można wywieść z wykorzystaniem Spróbuj określając argumenty typu jawnie.”:

Func<int> x = Test(() => 
    { 
     int i = 0; 
     return() => i; 
    }); 

Chyba chciałbym tylko wiedzieć, dlaczego działa w ten sposób i jakimi sposobami obejść.

+0

bardzo podobne pytanie, ale nie do końca takie same http://stackoverflow.com/questions/6090159/inferring-generic-types-with-functional-composition –

Odpowiedz

7

Powiedziałbym, że prawidłowa odpowiedź na pytanie jest przez E.Lippert w SO Why can't an anonymous method be assigned to var?

Ale niech nam grać z przykładu trochę:

Func<Func<int>> f =() => 
{ 
    int i = 0; 
    return() => i; 
}; 

Func<int> x = Test(f); //it compiles OK 

żadnego problemu typu wnioskowania z listy Func<T> Test<T>(Func<Func<T>> func) tutaj. Problem jest ukryty, ponieważ używasz anonimowego wyrażenia lambda, którego rodzaju nie można wywnioskować. Spróbuj tego:

var f =() => 
{ 
    int i = 0; 
    return() => i; 
}; 

Daje Compiler Error CS0815 mówiąc

Nie można przypisać wyrażenia lambda do niejawnie wpisany zmiennej lokalnej

i wyjaśnienie jest:

An wyrażenie używane jako inicjator dla niejawnie wpisanego zmienna musi mieć typ. Ponieważ wyrażeń funkcji anonimowych, wyrażeń grup metod i wyrażenia literowego zerowego nie ma typu , nie są one odpowiednie inicjalizatory. Niejawnie wpisana zmienna nie może zostać zainicjalizowana z wartością pustą w deklaracji, , chociaż później można mu przypisać wartość o wartości null.

Teraz spróbujmy jeszcze jedno:

var x = Test(() => 
{ 
    Func<int> f =() => 0; 
    return f; 
}); 

To kompiluje również.Tak więc problem z oryginalnego przykładu było faktycznie z tej linii:

return() => i; 

Możemy pójść dalej i według tego, co Eric Lippert mówi w jego odpowiedź zapewnienia innej funkcji, by zakończyć to:

static Func<T> GetFunc<T>(Func<T> f) { return f; } 

Teraz można przepisać swój kod, taki jak:

var x = Test(() => 
{ 
    int i = 0; 
    return GetFunc(() => i); 
}); 

I działa również.

Jednakże, o ile rozumiem, wszystko to jest kosztem ogólnym i należy po prostu podać wyraźny typ. O ile te obejścia są odpowiednie, jeśli potrzebujesz lambda, zwróć obiekt typu anonimowego.

Powiązane problemy