Pergunta

No C# 3.0, você pode criar aula anônima com a seguinte sintaxe

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

Existe uma maneira de adicionar essas aulas anônimas a uma lista genérica?

Exemplo:

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);

Outro exemplo:

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

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

Solução

Você poderia fazer:

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

Existem muitas maneiras de esfolar esse gato, mas basicamente todos eles usarão a inferência de tipo em algum lugar - o que significa que você precisa chamar um método genérico (possivelmente como um método de extensão). Outro exemplo pode ser:

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

var list = CreateList(o, o1);

Você entendeu a ideia :)

Outras dicas

Aqui está a resposta.

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);

Existem muitas maneiras de fazer isso, mas algumas das respostas aqui estão criando uma lista que contém elementos de lixo, o que exige que você limpe a lista.

Se você estiver procurando uma lista vazia do tipo genérico, use uma seleção contra uma lista de tuplas para fazer a lista vazia. Nenhum elemento será instanciado.

Aqui está a liner para criar uma lista vazia:

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

Então você pode adicionar a ele usando seu tipo genérico:

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

Como alternativa, você pode fazer algo abaixo para criar a lista vazia (mas eu prefiro o primeiro exemplo porque você pode usá -lo para uma coleção povoada de tuplas):

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

Não exatamente, mas você pode dizer List<object> E as coisas vão funcionar. No entanto, list[0].Id não vai funcionar.

Isso vai funcionar em tempo de execução em C# 4.0 por ter um List<dynamic>, ou seja, você não vai ficar com Intellisense.

Eu acho

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

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

vai funcionar.

Você também pode considerar escrever assim:

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

Eu geralmente uso o seguinte; Principalmente porque você "inicia" com uma lista vazia.

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

Ultimamente, tenho escrito assim: em vez disso:

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

Usar o método de repetição também permitiria que você faça:

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

.. que fornece a lista inicial com o primeiro item já adicionado.

Você pode fazer isso no seu código.

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

Eu verifiquei o IL em várias respostas. Este código fornece com eficiência uma lista vazia:

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

Na versão mais recente 4.0, pode usar dinâmico como abaixo

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

Aqui está minha tentativa.

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

Cheguei a isso quando escrevi algo semelhante para fazer uma lista anônima para um tipo personalizado.

Aqui está outro método de criar uma lista de tipos anônimos que permite começar com uma lista vazia, mas ainda tem acesso ao IntelliSense.

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

Se você quiser manter o primeiro item, basta colocar uma letra na string.

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

Em vez disso:

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);

Você poderia fazer isso:

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);

No entanto, você receberá um erro do CompileTime se tentar fazer algo assim em outro escopo, embora funcione em tempo de execução:

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); 
    }
}

O problema é que apenas os membros do objeto estão disponíveis em tempo de execução, embora o Intellisense mostre as propriedades Eu iria e nome.

No .NET 4.0, uma solução é usar a palavra -chave dinâmico istead de objeto no código acima.

Outra solução é usar a reflexão para obter as propriedades

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);

Você pode criar uma lista de dinâmicos.

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

"Dynamic" é inicializado pelo primeiro valor agregado.

Você pode fazer desta maneira:

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 um pouco "hacky", mas funciona - se você realmente precisa ter uma lista e não pode simplesmente usar a matriz anônima.

Esta é uma pergunta antiga, mas pensei em colocar minha resposta C# 6. Muitas vezes tenho que configurar dados de teste que são facilmente inseridos no código como uma lista de tuplas. Com algumas funções de extensão, é possível ter esse formato agradável e compacto, sem repetir os nomes em 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 });

Isso dá a um iEnumerable - se você deseja uma lista para a qual você possa adicionar, basta adicionar tolist ().

A magia vem de métodos de adição de extensão personalizada para tuplas, conforme descrito em 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...

}

A única coisa que não gosto é que os tipos sejam separados dos nomes, mas se você realmente não deseja fazer uma nova classe, essa abordagem ainda permitirá que você tenha dados legíveis.

Para o seu segundo exemplo, onde você precisa inicializar um novo List<T>, uma idéia é criar uma lista anônima e depois limpá -la.

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

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

Ou como um método de extensão, deve ser mais 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();

Ou provavelmente ainda mais curto,

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

Derivado de esta resposta, Criei dois métodos que poderiam fazer a tarefa:

    /// <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>();
    }

Você pode usar os 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 resposta Tem uma ideia semelhante, mas eu não vi isso até depois de fazer esses métodos.

Tente com isso:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top