Possible Duplicate:
Why is Func<T> ambiguous with Func<IEnumerable<T>>?Generics, la risoluzione di sovraccarico e delegati (mi dispiace, non riescono a trovare un titolo migliore)
ho notato un problema molto strano sovraccarico risoluzione con i generici ...
Prendere in considerazione i seguenti metodi:
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, testato in LINQPad)
Se provo a chiamare Foo
con un'espressione lambda come selettore , Tutto funziona bene:
Foo(42, x => x); // prints "int"
Ma se sostituisco x => x
con Identity
, il compilatore non può decidere tra i 2 Foo
sovraccarichi:
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>)'
Come può il secondo sovraccarico di essere un valido candidato? L'inferenza di tipo determina correttamente che TSource
è int
, quindi il parametro T
per il metodo Identity
deve essere int
pure, in modo che il tipo di ritorno deve essere int
troppo ... Identity
potrebbe essere un Func<int,int>
o un Func<double,double>
, ma non un Func<int,double>
!
E peggiora! Anche se specifico esplicitamente tutti i parametri di tipo, ottengo lo stesso errore:
Foo<int>(42, Identity<int>); // The call is ambiguous...
Come può esserci qualche ambiguità qui? Per quanto posso dire, non c'è modo in cui il sovraccarico che prende un Func<int,double>
può essere un candidato. Immagino che la spiegazione debba essere da qualche parte nelle specifiche, ma non riesco a trovare il bit pertinente ... o potrebbe essere un bug nel compilatore, ma immagino sia improbabile.
Nota che funziona se creo esplicitamente il delegato:
Foo(42, new Func<int, int>(Identity)); // prints "int"
Quindi, qualcuno potrebbe spiegare che cosa sta succedendo qui? Inoltre, perché funziona con un lambda ma non con un gruppo di metodi?
Aspettando pazientemente che Eric Lippert pubblichi * la * risposta. –
Cosa succede sotto C# 3? Sospetto che questo possa avere qualcosa a che fare con la varianza di tipo nei generici. –
@Anon, non ho provato con C# 3, ma non penso che abbia nulla a che fare con la varianza, perché la varianza non si applica ai tipi di valore –