Possible Duplicate:
Why is Func<T> ambiguous with Func<IEnumerable<T>>?Generics, Überladungsauflösung und Delegierten
ich (sorry, kann keinen besseren Titel finden) eine sehr seltsame Überladungsauflösung Problem mit Generika bemerkt ...
Betrachten Sie die folgenden Methoden:
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, getestet in LINQPad)
Wenn ich versuche, Foo
mit einem Lambda-Ausdruck als Wähler zu nennen , Funktioniert alles einwandfrei:
Foo(42, x => x); // prints "int"
Aber wenn ich x => x
mit Identity
ersetzen, kann der Compiler nicht zwischen den 2 Foo
Überlastungen entscheiden:
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>)'
Wie kann die zweite Überlastung sein ein gültiger Kandidat? Typinferenz bestimmt richtig, dass TSource
ist int
, so dass die T
Parameter für die Identity
Methode hat int
auch sein, so dass der Rückgabetyp hat int
zu sein ... Identity
ein Func<int,int>
oder ein Func<double,double>
sein könnte, aber nicht ein Func<int,double>
!
Und es wird schlimmer! Selbst wenn ich alle Typparameter explizit spezifiziere, erhalte ich immer noch den gleichen Fehler:
Foo<int>(42, Identity<int>); // The call is ambiguous...
Wie kann es hier eine Mehrdeutigkeit geben? Soweit ich das beurteilen kann, gibt es keine Möglichkeit, die Überlastung, die ein Func<int,double>
nimmt, ein Kandidat sein kann. Ich denke, die Erklärung muss irgendwo in den Spezifikationen sein, aber ich kann das relevante Bit nicht finden ... oder es könnte ein Fehler im Compiler sein, aber ich denke, es ist unwahrscheinlich.
Beachten Sie, dass es funktioniert, wenn ich den Delegaten explizit erstellen:
Foo(42, new Func<int, int>(Identity)); // prints "int"
So könnte jemand erklären, was hier vor sich geht? Warum funktioniert es auch mit einem Lambda, aber nicht mit einer Methodengruppe?
Geduldig warten auf Eric Lippert * die * Antwort zu posten. –
Was passiert unter C# 3? Ich vermute, dass dies etwas mit Typvarianz in Generika zu tun haben könnte. –
@Anon, ich habe nicht mit C# 3 versucht, aber ich glaube nicht, dass es etwas mit Varianz zu tun hat, da die Varianz nicht auf Werttypen –