Possible Duplicate:
Why is Func<T> ambiguous with Func<IEnumerable<T>>?rodzajowych, rozdzielczość przeciążenie i delegatów (przepraszam, nie mogę znaleźć lepszego tytuł)
zauważyłem bardzo dziwne przeciążenie rozdzielczość problem z rodzajowych ...
rozważyć następujące metody:
static void Foo<TSource>(TSource element, Func<TSource, int> selector)
{
"int".Dump();
}
static void Foo<TSource>(TSource element, Func<TSource, double> selector)
{
"double".Dump();
}
static T Identity<T>(T value)
{
return value;
}
(C# 4, testowany w LINQPad)
przypadku próby wywołania Foo
z wyrażeniem lambda selektora Wszystko działa poprawnie:
Foo(42, x => x); // prints "int"
Ale jeśli mogę wymienić x => x
z Identity
, kompilator nie może zdecydować się pomiędzy 2 Foo
przeciążeń:
Foo(42, Identity);
// The call is ambiguous between the following methods or properties:
// 'UserQuery.Foo<int>(int, System.Func<int,int>)' and
// 'UserQuery.Foo<int>(int, System.Func<int,double>)'
Jak drugi przeciążenie być prawidłowym kandydatem? Rodzaj wnioskowanie poprawnie określa, że TSource
jest int
, więc parametr T
dla metody Identity
musi być int
, tak więc typ zwracany musi być int
zbyt ... Identity
może być Func<int,int>
lub Func<double,double>
, ale nie Func<int,double>
!
I robi się coraz gorzej! Nawet jeśli jawnie określę wszystkie parametry typu, nadal otrzymuję ten sam błąd:
Foo<int>(42, Identity<int>); // The call is ambiguous...
Jak tu może występować dowolna dwuznaczność? O ile mogę powiedzieć, nie ma mowy, że przeciążenie, które bierze Func<int,double>
może być kandydatem. Myślę, że wyjaśnienie musi znajdować się gdzieś w specyfikacjach, ale nie mogę znaleźć odpowiedniego fragmentu ... lub może to być błąd w kompilatorze, ale myślę, że jest to mało prawdopodobne.
Zauważ, że to działa, jeśli jawnie utworzyć Delegat:
Foo(42, new Func<int, int>(Identity)); // prints "int"
Więc może ktoś wyjaśnić, co tu się dzieje? Ponadto, dlaczego działa z lambda, ale nie z grupą metod?
Cierpliwie czekając na Erica Lipperta, aby opublikował * odpowiedź *. –
Co dzieje się w C# 3? Podejrzewam, że może to mieć coś wspólnego z wariancją typu w generycznych. –
@Anon, nie próbowałem z C# 3, ale nie sądzę, że ma to coś wspólnego z wariancją, ponieważ wariancja nie ma zastosowania do typów wartości –