2013-04-24 14 views
16

Perché non posso trasmettere un List<AnonymousObject> a un List<dynamic>? Ho questa seguente codice:Elenco cast di tipo anonimo a elenco di oggetti dinamici

var datasource = someList.Select(o => new { x = o.A, y = o.B }); 
dgvSomeGridView.DataSource = datasource.ToList(); 
dgvSomeGridView.DataBind(); 

Poi ho accedere al GridView.DataSource con il seguente codice:

var ds = ((List<dynamic>)dgvSomeGridView.DataSource); 
.... 

Ma genera un errore sulla linea dove ho gettato a List<dynamic>, si dice:

Impossibile trasmettere l'oggetto del tipo System.Collections.Generic.List'1[<>f__AnonymousType0'8[System.Int32,System.String]] al tipo System.Collections.Generic.List'1[System.Object].

Perché non posso lanciare un elenco di tipo anonimo a un dynamic, o come l'errore dice a un tipo object? Come posso risolvere questo?

Il mio codice è in C#, framework 4.0, build in VS2010 Pro, la piattaforma è ASP.NET.

Si prega di aiutare, grazie in anticipo.

risposta

35

Dal List<T> è in variante, non co-variante, quindi bisogna gettato in IEnumerable<dynamic> che supporta co-variante:

var ds = ((IEnumerable<dynamic>)dgvSomeGridView.DataSource).ToList(); 

Per ulteriori information about covariant

+1

non dimenticare di aggiungere ' using System.Linq; ' nell'intestazione del documento nel caso in cui non hai ancora –

6

In primo luogo, Casting con generici non funziona in questo modo Questo cast non è valido:

List<string> source = GetStrings(); 
List<object> source2 = (List<object>) source; 

La ragione è che l'elenco non è co-variante. Se lo fosse, potresti source2.Add(source2); e improvvisamente source1 contiene se stesso quando dovrebbe avere solo stringhe.

In secondo luogo, Anonymous types sono solo classi di compilatore dichiarate con proprietà readonly e semantica dell'uguaglianza di valore. Se hai creato una classe con proprietà readonly e semantica di equality value, la tua classe sarebbe la stessa di un tipo anonimo, tranne che il tuo tipo avrebbe un nome determinato dallo sviluppatore, mentre il tipo anonimo ha un nome determinato dal compilatore. I tipi di Anon non sono speciali.

In terzo luogo, le variabili dynamic sono un modo per aggirare il controllo del tipo di compilatore. Non vanno in giro il controllo del tipo di runtime. Puoi usare la sintassi di casting C# per convertire esplicitamente il tipo in dinamico ... nota: questo non è un cast! Non è possibile eseguire un cast runtime su un tipo che non esiste in fase di runtime.

Tuttavia, le operazioni che contengono espressioni di tipo dinamico non vengono risolte o controllate dal compilatore. Il compilatore raggruppa le informazioni sull'operazione e tali informazioni vengono successivamente utilizzate per valutare l'operazione in fase di esecuzione. Come parte del processo, le variabili di tipo dynamic sono compilate in variabili di tipo object. Pertanto, digita dynamic esiste solo in fase di compilazione, non in fase di esecuzione.

static void convertToDynamic() 
{ 
    dynamic d; 
    int i = 20; 
    d = (dynamic)i; 
    Console.WriteLine(d); 

    string s = "Example string."; 
    d = (dynamic)s; 
    Console.WriteLine(d); 

    DateTime dt = DateTime.Today; 
    d = (dynamic)dt; 
    Console.WriteLine(d); 

} 
// Results: 
// 20 
// Example string. 
// 2/17/2009 9:12:00 AM 

Infine, se si vuole ancora un List<dynamic>, fare questo:

var anonList = GetAnonList(); 
List<dynamic> dynamicList = anonList.Select(x => (dynamic)x).ToList(); 

Ma si potrebbe altrettanto facilmente fare questo:

var anonList = GetAnonList(); 
List<object> objectList = anonList.Cast<object>().ToList(); 
+0

Grande, questo funziona per me! –