Il codice seguente è valida:Assegnare una funzione di delegato che restituisce un tipo anonimo a una variabile
IEnumerable<SomeThing> things = ...;
// map type SomeThing to a new anonymous type, resulting in a strongly typed
// sequence based on an anon type
var newList = things.Select(item =>
{
return new
{
ID = item.ID,
DateUpdatedOrCreated = ((DateTime)(item.DateUpdated ??
item.DateCreated)).ToShortDateString(),
Total = item.Part1 + item.Part2
};
});
newList appare ora in Visual Studio come IEnumerable<'a>
ed è fortemente tipizzato con il tipo anonimo creato nella funzione. È così bello
Quello che non riesco a fare è trovare un modo per assegnare solo l'espressione lambda (e non l'enumerazione) a una variabile implicitamente tipizzata. Anche se il compilatore non ha alcun problema con il tipo anonimo nel contesto di cui sopra, se provo (diciamo)
var func = (SomeThing item)=> {
return new { ... };
};
ottengo l'errore "non può assegnare espressione lambda al implicitamente-digitato variabile locale". Questa sembra una strana limitazione del compilatore; a meno che non mi manchi qualcosa, i tipi sono altrettanto non ambigui nel secondo esempio come sono nel primo: entrambi i parametri di tipo sono ben definiti.
C'è un modo per farlo? Dal momento che è un tipo anonimo, ovviamente, non ho modo di usare un tipo per assegnarlo esplicitamente, quindi sembra che sarei bloccato a fare una classe per il tipo di output, se non lo fosse.
Aggiornamento
Poco dopo essere andato sul mio modo allegro con la risposta di Jon Skeet, ho trovato un dilemma simile istanziare le classi. Nel caso non sia ovvio, lo stesso trucco può essere utilizzato per creare classi fortemente tipizzate utilizzando tipi anonimi dedotti.
class Processor<T,U>
{
public Processor(Func<T,U> func) {
}
}
// func is a delegate with anon return type created using method in answer below
var instance = new Processor(func); // does not compile! Requires type arguments!
non possono essere creati direttamente, ma possono essere creati più o meno allo stesso modo in cui il trucco di seguito:
public static Processor<T,U> Create<T,U>(Func<T,U> func) {
return new Processor<T,U>(func);
}
var instance = Processor.Create(func); // all good
Questo funziona perché l'inferenza di tipo per generici è più intelligente dell'inferenza di tipo per 'var'. (Presumo che jon potrebbe essere in grado di spiegare il perché, anche se non posso.) – Servy
Buona risposta. Informazioni aggiuntive: Funziona perché non è necessario specificare il tipo di variabile qui. Il compilatore non può solo inferire il tipo per la variabile perché ci sono più tipi di delegati tra cui potrebbe scegliere. – usr
@Servy: Non si tratta di essere più intelligenti in quanto tali, è una questione di essere in grado di specificare che si desidera un delegato 'Func', ma specificandolo in modo generico. –