Domanda

In C # 3.0 puoi creare una classe anonima con la seguente sintassi

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

C'è un modo per aggiungere queste classi anonime a un elenco generico?

Esempio:

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

Un altro esempio:

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

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}
È stato utile?

Soluzione

Potresti fare:

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

Esistono molti modi per scuoiare questo gatto, ma fondamentalmente useranno tutti l'inferenza del tipo da qualche parte - il che significa che devi chiamare un metodo generico (possibilmente come metodo di estensione). Un altro esempio potrebbe essere:

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

var list = CreateList(o, o1);

Hai avuto l'idea :)

Altri suggerimenti

Ecco la risposta.

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

Esistono molti modi per farlo, ma alcune delle risposte qui stanno creando un elenco che contiene elementi di immondizia, che richiede di cancellare l'elenco.

Se stai cercando un elenco vuoto di tipo generico, usa un Seleziona contro un elenco di tuple per creare un elenco vuoto. Nessun elemento verrà istanziato.

Ecco il one-liner per creare un elenco vuoto:

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

Quindi puoi aggiungervi usando il tuo tipo generico:

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

In alternativa, puoi fare qualcosa come sotto per creare l'elenco vuoto (Ma preferisco il primo esempio perché puoi usarlo anche per una raccolta popolata di Tuple):

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

Non esattamente, ma puoi dire List<object> e le cose funzioneranno. Tuttavia, list[0].Id non funzionerà.

Questo funzionerà in fase di runtime in C # 4.0 avendo un List<dynamic>, cioè non otterrai IntelliSense.

Suppongo

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

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

funzionerà.

Potresti anche considerare di scriverlo in questo modo:

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

Di solito uso quanto segue; principalmente perché poi " inizia " con un elenco vuoto.

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

Ultimamente, l'ho scritto in questo modo invece:

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

L'uso del metodo ripetizione ti permetterebbe anche di fare:

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

.. che ti dà l'elenco iniziale con il primo elemento già aggiunto.

Puoi farlo nel tuo codice.

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

Ho controllato l'IL su diverse risposte. Questo codice fornisce in modo efficiente un elenco vuoto:

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

Nell'ultima versione 4.0, puoi usare la dinamica come di seguito

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

Ecco il mio tentativo.

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

Mi sono inventato questo quando ho scritto qualcosa di simile per creare un elenco anonimo per un tipo personalizzato.

Ecco un altro metodo per creare un elenco di tipi anonimi che ti consente di iniziare con un elenco vuoto, ma hai ancora accesso a IntelliSense.

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

Se si desidera conservare il primo elemento, basta inserire una lettera nella stringa.

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

Invece di questo:

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

Puoi farlo:

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

Tuttavia, otterrai un errore compiletime se provi a fare qualcosa del genere in un altro ambito, sebbene funzioni in fase di esecuzione:

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

Il problema è che solo i membri di Object sono disponibili in fase di esecuzione, sebbene intellisense mostrerà le proprietà id e nome .

In .net 4.0 una soluzione consiste nell'utilizzare la parola chiave dinamica anziché oggetto nel codice sopra.

Un'altra soluzione è utilizzare la riflessione per ottenere le proprietà

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

Puoi creare un elenco di dinamici.

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

quot; & Dinamica quot; viene inizializzato dal primo valore aggiunto.

Puoi farlo in questo modo:

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

Sembra un po '" hacky " per me, ma funziona - se hai davvero bisogno di avere un elenco e non puoi semplicemente usare l'array anonimo.

Questa è una vecchia domanda, ma ho pensato di inserire la mia risposta C # 6. Spesso devo impostare i dati di test che possono essere facilmente inseriti nel codice come un elenco di tuple. Con un paio di funzioni di estensione, è possibile avere questo formato carino e compatto, senza ripetere i nomi su ogni voce.

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

Questo dà un IEnumerable - se vuoi un elenco che puoi aggiungere, allora aggiungi ToList ().

La magia viene dall'estensione personalizzata Aggiungi metodi per le tuple, come descritto in 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...

}

L'unica cosa che non mi piace è che i tipi sono separati dai nomi, ma se davvero non vuoi creare una nuova classe, questo approccio ti permetterà comunque di avere dati leggibili.

Per il tuo secondo esempio, in cui devi inizializzare un nuovo List<T>, un'idea è quella di creare un elenco anonimo e quindi cancellarlo.

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

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

O come metodo di estensione, dovrebbe essere più semplice:

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 probabilmente anche più breve,

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

Derivando da questa risposta , ho trovato due metodi che potrebbero svolgere il compito:

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

Puoi usare metodi come

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

Questa risposta ha un'idea simile, ma non l'ho vista fino a dopo aver fatto quei metodi.

Prova con questo:

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);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top