Pregunta

En C# 3.0 puedes crear una clase anónima con la siguiente sintaxis

var o = new { Id = 1, Name = "Foo" };

¿Hay alguna manera de agregar estas clases anónimas a una lista genérica?

Ejemplo:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

List<var> list = new List<var>();
list.Add(o);
list.Add(o1);

Otro ejemplo:

List<var> list = new List<var>();

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}
¿Fue útil?

Solución

Podrías hacer:

var list = new[] { o, o1 }.ToList();

Hay muchas formas de desollar este gato, pero básicamente todas usarán inferencia de tipos en alguna parte, lo que significa que debe llamar a un método genérico (posiblemente como un método de extensión). Otro ejemplo podría ser:

public static List<T> CreateList<T>(params T[] elements)
{
     return new List<T>(elements);
}

var list = CreateList(o, o1);

Tienes la idea :)

Otros consejos

Aquí está la respuesta.

string result = String.Empty;

var list = new[]
{ 
    new { Number = 10, Name = "Smith" },
    new { Number = 10, Name = "John" } 
}.ToList();

foreach (var item in list)
{
    result += String.Format("Name={0}, Number={1}\n", item.Name, item.Number);
}

MessageBox.Show(result);

Hay muchas formas de hacer esto, pero algunas de las respuestas aquí están creando una lista que contiene elementos basura, lo que requiere que borre la lista.

Si está buscando una lista vacía del tipo genérico, use un Seleccionar contra una Lista de tuplas para hacer la lista vacía. No se instanciará ningún elemento.

Aquí está la línea para crear una lista vacía:

 var emptyList = new List<Tuple<int, string>>()
          .Select(t => new { Id = t.Item1, Name = t.Item2 }).ToList();

Luego puedes agregarle usando tu tipo genérico:

 emptyList.Add(new { Id = 1, Name = "foo" });
 emptyList.Add(new { Id = 2, Name = "bar" });

Como alternativa, puede hacer algo como a continuación para crear la lista vacía (pero, prefiero el primer ejemplo porque también puede usarlo para una colección poblada de tuplas):

 var emptyList = new List<object>()
          .Select(t => new { Id = default(int), Name = default(string) }).ToList();   

No exactamente, pero se puede decir List<object> y las cosas funcionarán.Sin embargo, list[0].Id no funcionará.

esto funcionará en tiempo de ejecución en C# 4.0 al tener un List<dynamic>, es decir, no obtendrá IntelliSense.

supongo

List<T> CreateEmptyGenericList<T>(T example) {
    return new List<T>();
}

void something() {
    var o = new { Id = 1, Name = "foo" };
    var emptyListOfAnonymousType = CreateEmptyGenericList(o);
}

funcionará.

También podría considerar escribirlo así:

void something() {
    var String = string.Emtpy;
    var Integer = int.MinValue;
    var emptyListOfAnonymousType = CreateEmptyGenericList(new { Id = Integer, Name = String });
}

Usualmente uso lo siguiente; principalmente porque luego " inicio " con una lista que está vacía.

var list = Enumerable.Range(0, 0).Select(e => new { ID = 1, Name = ""}).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );
//etc.

Últimamente, lo he estado escribiendo así:

var list = Enumerable.Repeat(new { ID = 1, Name = "" }, 0).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );

Usar el método de repetición también le permitiría hacer:

var myObj = new { ID = 1, Name = "John" };
var list = Enumerable.Repeat(myObj, 1).ToList();
list.Add(new { ID = 2, Name = "Liana" });

..que le da la lista inicial con el primer elemento ya agregado.

Puede hacer esto en su código.

var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });

Revisé el IL en varias respuestas. Este código proporciona eficientemente una Lista vacía:

    using System.Linq;
    …
    var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();

En la última versión 4.0, puede usar dinámicas como a continuación

var list = new List<dynamic>();
        list.Add(new {
            Name = "Damith"
    });
        foreach(var item in list){
            Console.WriteLine(item.Name);
        }
    }

Aquí está mi intento.

List<object> list = new List<object> { new { Id = 10, Name = "Testing1" }, new {Id =2, Name ="Testing2" }}; 

Se me ocurrió esto cuando escribí algo similar para hacer una Lista anónima para un tipo personalizado.

Aquí hay otro método para crear una Lista de tipos anónimos que le permite comenzar con una lista vacía, pero aún así tener acceso a IntelliSense.

var items = "".Select( t => new {Id = 1, Name = "foo"} ).ToList();

Si desea conservar el primer elemento, simplemente ponga una letra en la cadena.

var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();

En lugar de esto:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List <var> list = new List<var>(); 
list.Add(o); 
list.Add(o1);

Podrías hacer esto:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List<object> list = new List<object>(); 
list.Add(o); 
list.Add(o1);

Sin embargo, obtendrá un error en tiempo de compilación si intenta hacer algo como esto en otro ámbito, aunque funciona en tiempo de ejecución:

private List<object> GetList()
{ 
    List<object> list = new List<object>();
    var o = new { Id = 1, Name = "Foo" }; 
    var o1 = new { Id = 2, Name = "Bar" }; 
    list.Add(o); 
    list.Add(o1);
    return list;
}

private void WriteList()
{
    foreach (var item in GetList()) 
    { 
        Console.WriteLine("Name={0}{1}", item.Name, Environment.NewLine); 
    }
}

El problema es que solo los miembros de Object están disponibles en tiempo de ejecución, aunque intellisense mostrará las propiedades id y name .

En .net 4.0 una solución es usar la palabra clave dinámica en lugar de objeto en el código anterior.

Otra solución es usar la reflexión para obtener las propiedades

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            var anonymous = p.GetList(new[]{
                new { Id = 1, Name = "Foo" },       
                new { Id = 2, Name = "Bar" }
            });

            p.WriteList(anonymous);
        }

        private List<T> GetList<T>(params T[] elements)
        {
            var a = TypeGenerator(elements);
            return a;
        }

        public static List<T> TypeGenerator<T>(T[] at)
        {
            return new List<T>(at);
        }

        private void WriteList<T>(List<T> elements)
        {
            PropertyInfo[] pi = typeof(T).GetProperties();
            foreach (var el in elements)
            {
                foreach (var p in pi)
                {
                    Console.WriteLine("{0}", p.GetValue(el, null));
                }
            }
            Console.ReadLine();
        }
    }
}
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);

Puede crear una lista de dinámica.

List<dynamic> anons=new List<dynamic>();
foreach (Model model in models)
{
   var anon= new
   {
      Id = model.Id,
      Name=model.Name
   };
   anons.Add(anon);
}

" dinámico " se inicializa con el primer valor agregado.

Puedes hacerlo de esta manera:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

var array = new[] { o, o1 };
var list = array.ToList();

list.Add(new { Id = 3, Name = "Yeah" });

Parece un poco " hacky " para mí, pero funciona, si realmente necesita tener una lista y no puede simplemente usar la matriz anónima.

Esta es una vieja pregunta, pero pensé en poner mi respuesta C # 6. A menudo tengo que configurar datos de prueba que se ingresan fácilmente en el código como una lista de tuplas. Con un par de funciones de extensión, es posible tener este formato agradable y compacto, sin repetir los nombres en cada entrada.

var people= new List<Tuple<int, int, string>>() {
    {1, 11, "Adam"},
    {2, 22, "Bill"},
    {3, 33, "Carol"}
}.Select(t => new { Id = t.Item1, Age = t.Item2, Name = t.Item3 });

Esto proporciona un IEnumerable: si desea una lista a la que pueda agregar, simplemente agregue ToList ().

La magia proviene de la extensión personalizada Agregar métodos para tuplas, como se describe en https://stackoverflow.com/a/27455822/4536527 .

public static class TupleListExtensions    {
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
            T1 item1, T2 item2)       {
        list.Add(Tuple.Create(item1, item2));
    }

    public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
            T1 item1, T2 item2, T3 item3) {
        list.Add(Tuple.Create(item1, item2, item3));
    }

// and so on...

}

Lo único que no me gusta es que los tipos están separados de los nombres, pero si realmente no desea crear una nueva clase, este enfoque aún le permitirá tener datos legibles.

Para su segundo ejemplo, donde debe inicializar un nuevo List<T>, una idea es crear una lista anónima y luego borrarla.

var list = new[] { o, o1 }.ToList();
list.Clear();

//and you can keep adding.
while (....)
{
    ....
    list.Add(new { Id = x, Name = y });
    ....
}

O como método de extensión, debería ser más fácil:

public static List<T> GetEmptyListOfThisType<T>(this T item)
{
    return new List<T>();
}

//so you can call:
var list = new { Id = 0, Name = "" }.GetEmptyListOfThisType();

O probablemente incluso más corto,

var list = new int[0].Select(x => new { Id = 0, Name = "" }).Tolist();

Derivado de esta respuesta , se me ocurrieron dos métodos que podrían hacer la tarea:

    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't called, it is only used
    /// for the needed type inference. This overload is for when you don't have an instance of the anon class
    /// and don't want to make one to make the list.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(Func<T> definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }
    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't added to the list, it is
    /// only used for the needed type inference. This overload is for when you do have an instance of the anon
    /// class and don't want the compiler to waste time making a temp class to define the type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(T definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }

Puedes usar los métodos como

var emptyList = CreateListOfAnonType(()=>new { Id = default(int), Name = default(string) });
//or
var existingAnonInstance = new { Id = 59, Name = "Joe" };
var otherEmptyList = CreateListOfAnonType(existingAnonInstance);

Esta respuesta tiene una idea similar, pero no la vi hasta después de que hice esos métodos.

Pruebe con esto:

var result = new List<object>();

foreach (var test in model.ToList()) {
   result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}
static void Main()
{
    List<int> list = new List<int>();
    list.Add(2);
    list.Add(3);
    list.Add(5);
    list.Add(7);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top