Prefazione: consente di passare alla modifica se si desidera la spiegazione completa. Spoiler: I metodi di estensione sono un trucco del compilatore e in realtà hanno un argomento in più di quello che sembrano quando li invochi.
È nella risoluzione del gruppo metodo. Apparentemente il compilatore C# non impiega il tempo per capire se il metodo che si sta usando ha sovraccarichi o meno; richiede sempre un cast esplicito. Partenza:
What is a method group in C#?
Method Inference does not work with method group
Il gruppo metodo che torna da reader.GetDoubleOrNull
è limitato giù da quello che si tenta di lanciare a: GetDoubleOrNull
potrebbe riferirsi a qualsiasi numero di metodi di overload con quel nome. Devi castarlo esplicitamente.
È interessante notare che non si può nemmeno assegnare un gruppo di metodo per una variabile implicitamente tipizzate per lo stesso motivo:
var x = reader.GetDoubleOrNull;
fallisce la compilazione perché richiede un cast esplicito.
Edit Sono abbastanza sicuro che la confusione qui ha a che fare con i metodi di estensione:
controllare il seguente classe di test:
public static class Extensions
{
public static List<T> GetList<T>(this IDataReader reader, Func<string, T> del)
{
throw new NotImplementedException();
}
public static double? GetDoubleOrNull(this IDataReader reader, string columnName)
{
throw new NotImplementedException();
}
public static double? blah(this string s)
{
throw new NotImplementedException();
}
}
È possibile chiamare con successo
var x = reader.GetList(Extensions.blah);
Perché questo potrebbe essere? blah
è anche un metodo di estensione statica, quindi, in base alle prove, sembrerebbe che la riga precedente non debba essere compilata. A complicare ulteriormente le cose, aggiungiamo questo metodo:
public static List<T> GetList2<T>(this IDataReader reader, Func<IDataReader, string, T> del)
{
throw new NotImplementedException();
}
È ora possibile chiamare
x = reader.GetList2(Extensions.GetDoubleOrNull);
e sarà compilato correttamente. Cosa dà?
Ecco la risposta: Metodi di estensione non in realtà aggiungere metodi ai propri oggetti. Sono davvero un trucco per il compilatore che ti permette di programmare come se quei metodi facessero parte delle tue classi. Da here:
Nel codice si richiama il metodo di estensione con metodo istanza sintassi. Tuttavia, il linguaggio intermedio (IL) generato dal compilatore converte il codice in una chiamata sul metodo statico. Pertanto, il principio di incapsulamento non viene realmente violato . In effetti, i metodi di estensione non possono accedere alle variabili private nel tipo che stanno estendendo.
Così, quando si chiama
var x = reader.GetDoubleOrNull("myColumnName");
ciò che viene effettivamente compilato ed eseguito è essenzialmente questo (una chiamata perfettamente legittima, anche se è un metodo di estensione):
var x = Extensions.GetDoubleOrNull(reader, "myColumnName");
Così , quando si tenta di utilizzare GetDoubleOrNull
come argomento per un Func<string, double?>
, il compilatore sta andando "Posso trasformare GetDoubleOrNull
in un Func<IDataReader, string, double?>
perché ha due argomenti, ma io non k ora come trasformarlo in un Func<string, double?>
"
Anche se si sta chiamando come se si tratta di un metodo di IDataReader
con una sola arg esempio, non è: è solo un metodo statico con due argomenti che il C# il compilatore ti ha indotto a pensare è parte di IDataReader
.
Molto interessante. Un cast esplicito '' var x = reader.GetList ((Func) Reader.GetDoubleOrNull) '' Funziona anche. Il ricercatore contrassegna il cast come ridondante, ma senza di esso la compilazione fallisce. Jon Skeet è in giro? –
C'è un modo per invocare Jon Skeet (o forse Eric Lippert)? Dì il loro nome tre volte o qualcosa del genere? – Chris
correlati: http://stackoverflow.com/questions/7745852/method-inference-does-not-work-with-method-group e http://stackoverflow.com/questions/2057146/compiler-ambiguous-invocation-error -anonymous-method-and-method-group-with-fun – AakashM