2010-10-14 20 views
22

Estoy llamando a un método que devuelve una variable de lista que contiene un C# Tipo de objetos anónimos. Por ejemplo:Trabajando con C# Anonymous Types

List<object> list = new List<object>(); 
foreach (Contact c in allContacts) { 
    list.Add(new { 
     ContactID = c.ContactID, 
     FullName = c.FullName 
    }); 
} 
return list; 

¿Cómo hacen referencia a esta propiedades de tipo en el código que estoy trabajando como por ejemplo

foreach (object o in list) { 
    Console.WriteLine(o.ContactID); 
} 

Sé que mi muestra no es posible, sólo he escribió de esa manera a Digo que necesito identificar exactamente cada propiedad del tipo anónimo.

Gracias!

Solución:

No sólo uno de la respuesta es correcta y/o sugerir una solución de trabajo. Terminé usando la Opción 3 de la respuesta de Greg. ¡Y aprendí algo muy interesante con respecto al dynamic en .NET 4.0!

+0

posible duplicado de [Acceso a C# Anónimo Tipo objetos] (http://stackoverflow.com/questions/713521/accessing-c-sharp-anonymous-type-objects) – nawfal

Respuesta

32

No puede devolver una lista de tipo anónimo, tendrá que ser una lista de object. Por lo tanto, perderá la información del tipo.

Opción 1
No utilice un tipo anónimo. Si intenta utilizar un tipo anónimo en más de un método, cree una clase real.

Opción 2
No abatido su tipo anónimo a object. (Debe estar en un método)

var list = allContacts 
      .Select(c => new { c.ContactID, c.FullName }) 
      .ToList(); 

foreach (var o in list) { 
    Console.WriteLine(o.ContactID); 
} 

Opción 3
Utilice la palabra clave dinámica. (4 .NET requiere)

foreach (dynamic o in list) { 
    Console.WriteLine(o.ContactID); 
} 

Opción 4
Uso alguna reflexión sucio.

+1

Opción 5. Devolver una lista de dos elementos Tuples (por ejemplo: 'List >'). (pero vaya para la opción 1.) –

+0

La opción 3 dice que echo de menos la carpeta de tiempo de ejecución de Dinamic. ¿Que es eso? ¿Debo importar algo? – Lorenzo

+3

+1 La opción 1 es realmente la mejor para reutilizar el tipo en diferentes métodos. –

3
foreach (var o in list) { 
    Console.WriteLine(o.ContactID); 
} 

esto sólo funcionará si la lista está IEnumerable<anonymous type>, así:

var list = allContacts.Select(c => new { 
     ContactID = c.ContactID, 
     FullName = c.FullName 
    }); 
} 

pero no se puede volver tipos anónimos, ya que debe definir el tipo de retorno (no se puede volver var) y los tipos anónimos no pueden tener nombres. deberías crear un tipo no anónimo si deseas pasarlo. En realidad, los tipos anónimos no deben usarse demasiado, excepto en el interior de las consultas.

+1

No puede devolver 'IEnumerable ' – Greg

+0

La devolución me da una advertencia que no puede hacer una conversión implícita entre IEnumerable y List . ¿Cómo debo cambiar la firma de mi método? – Lorenzo

+1

@Lorenzo como se mencionó, no puede devolver tipos anónimos, porque debe definir el tipo de devolución y los tipos anónimos no pueden tener nombres. deberías crear un tipo no anónimo si deseas pasarlo. En realidad, los tipos anónimos no deben usarse demasiado, excepto en el interior de las consultas. – Andrey

1

No puede hacer esto con tipos anónimos. Simplemente crea una clase/estructura de contacto y úsala.

List<object> list = new List<object>(); 
foreach (Contact c in allContacts) { 
    list.Add(c); 
} 

A continuación, puede hacer esto:

foreach (var o in list) { 
    Console.WriteLine(o.ContactID); 
} 

...o esto:

foreach (object o in list) { 
    Console.WriteLine(((Contact)o).ContactID); //Gives intellisense 
} 

Por supuesto debe en ese caso sólo lo hacen crear una lista de contactos en lugar de una lista de objetos:

List<Contact> list = new List<Contact>(); 
foreach (Contact c in allContacts) { 
    list.Add(c); 
} 

EDIT: Perdidas parte esencial de la cuestión. Ahora arreglado.
EDITAR: Se modificó la respuesta una vez más. Véase más arriba.

+0

o no es de tipo Contacto, es de tipo anónimo. –

+0

esto está mal. o no es una instancia de 'Contacto', sino instancia de tipo anónimo – Andrey

+0

Oh, se perdió esa parte. Léelo demasiado rápido. Los otros son correctos. Use 'var'. –

0

sustitución de objeto con var en para cada construcción puede funcionar

+4

'List ' es lo que sugiere? – Andrey

2

Si usted tiene un método como este:

List<object> GetContactInfo() { 
    List<object> list = new List<object>(); 
    foreach (Contact c in allContacts) { 
     list.Add(new { 
      ContactID = c.ContactID, 
      FullName = c.FullName 
     }); 
    } 
    return list; 
    } 

que realmente no debería hacer esto, pero no hay una técnica very ugly and not future-proof que puede utilizar :

static T CastByExample<T>(object target, T example) { 
    return (T)target; 
    } 

    // ..... 

    var example = new { ContactID = 0, FullName = "" }; 
    foreach (var o in GetContactInfo()) { 
    var c = CastByExample(o, example); 
    Console.WriteLine(c.ContactID); 
    } 

Se basa en el hecho (que puede cambiar!) que el compilador vuelve a utilizar los tipos anónimos para los tipos que tienen la misma "forma" (propiedades de nombres y tipos) . Como su "ejemplo" coincide con la "forma" del tipo en el método, se reutiliza el mismo tipo.

Las variables dinámicas en C# 4 son la mejor manera de resolver esto.

+8

Esto es grotesco, pero fascinante. – Greg

-1

, lo usaría

allContacts 
.Select(c => new { c.ContactID, c.FullName }) 
.ToList() 
.ForEach(c => { 
    ...do stuff; 
}); 

entonces ya no tienes que declarar en absoluto. yo creo que menos de declaración, a menos punto y coma conduce a una menor error

+1

Creo que te has perdido la verdadera pregunta. Por favor léelo otra vez cuidadosamente – Lorenzo

0

Sé que llego tarde a la fiesta pero la investigación de somthing más y encontramos esta article que responde a su pregunta.

Es posible convertir la lista de objetos nuevamente en el tipo anónimo.

public static void Main() 
    { 
     foreach (object item in GetList()) 
     { 
      var x = Cast(item, new { ContactID = 0, FullName = "" }); 
      Console.WriteLine(x.ContactID + " " + x.FullName); 
     } 

    } 

    public static IEnumerable<object> GetList() 
    { 
     yield return new { ContactID = 4, FullName = "Jack Smith" }; 
     yield return new { ContactID = 5, FullName = "John Doe" }; 
    } 

    public static T Cast<T>(object obj, T type) 
    { 
     return (T)obj; 
    } 
0

lista volver

public static void Main() 
{ 
    foreach (object item in GetList()) 
    { 
     var x = Cast(item, new { ContactID = 0, FullName = "" }); 
     Console.WriteLine(x.ContactID + " " + x.FullName); 
    } 

} 

public static IEnumerable<object> GetList() 
{ 
    yield return new { ContactID = 4, FullName = "Jack Smith" }; 
    yield return new { ContactID = 5, FullName = "John Doe" }; 
} 

public static T Cast<T>(object obj, T type) 
{ 
    return (T)obj; 
}