español - Trabajando con C#Anonymous Types
static dynamic c# (8)
Estoy llamando a un método que devuelve una variable de lista que contiene ac # Tipo anónimo de objetos. Por ejemplo:
List<object> list = new List<object>();
foreach ( Contact c in allContacts ) {
list.Add( new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
return list;
¿Cómo hago referencia a las propiedades de este tipo en el código en el que estoy trabajando, como por ejemplo
foreach ( object o in list ) {
Console.WriteLine( o.ContactID );
}
Sé que mi muestra no es posible, solo escribí de esa manera para decir que necesito identificar exactamente cada propiedad del tipo anónimo.
¡Gracias!
Solución :
No solo una de las respuestas es correcta y / o sugiere una solución de trabajo. Terminé usando la Opción 3 de la respuesta de Greg. ¡Y aprendí algo muy interesante sobre la dynamic
en .NET 4.0!
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 use un tipo anónimo. Si intenta utilizar un tipo anónimo en más de un método, cree una clase real.
opcion 2
No downcast 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
Use la palabra clave dinámica (Se requiere .NET 4)
foreach (dynamic o in list) {
Console.WriteLine(o.ContactID);
}
Opción 4
Usa un reflejo sucio
No puedes 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 );
}
Entonces puedes 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, en ese caso debería 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 );
}
EDITAR: se perdió la parte esencial de la pregunta. Ahora arreglado.
EDITAR: Cambió la respuesta una vez más. Véase más arriba.
Sé que llego tarde a la fiesta pero investigo algo más y encontré este article que responde a su pregunta.
Es posible convertir la lista de objetos 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;
}
Si tienes 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;
}
En realidad, no deberías hacer esto, pero hay una técnica muy fea y no a prueba de futuro que puedes usar:
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!) De que el compilador reutiliza tipos anónimos para tipos que tienen la misma "forma" (nombres y tipos de propiedades). Como su "ejemplo" coincide con la "forma" del tipo en el método, se reutiliza el mismo tipo.
Sin embargo, las variables dinámicas en C # 4 son la mejor manera de resolver esto.
lista de vuelta
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;
}
reemplazar objeto con var en cada construcción puede funcionar
yo usaría
allContacts
.Select(c => new { c.ContactID, c.FullName })
.ToList()
.ForEach(c => {
...do stuff;
});
entonces no necesitas declarar nada. creo que menos declaración, menos punto y coma conduce a menos errores
foreach ( var o in list ) {
Console.WriteLine( o.ContactID );
}
esto solo funcionará si la lista es IEnumerable<anonymous type>
, como esta:
var list = allContacts.Select(c => new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
pero no puede devolver tipos anónimos, porque debe definir el tipo de devolución (no puede devolver 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.