Ogólna lista anonimowych klas

W C# 3.0 można utworzyć klasę anonimową o następującej składni

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

Czy istnieje sposób, aby dodać te anonimowe klasy do ogólnej listy?

Przykład:

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

Inny Przykład:

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

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}
Author: leppie, 2009-03-04

22 answers

Możesz zrobić:

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

Istnieje wiele sposobów skórowania tego kota, ale zasadniczo wszystkie będą używać wnioskowania typu gdzieś - co oznacza, że musisz wywoływać metodę generyczną (prawdopodobnie jako metodę rozszerzenia). Innym przykładem może być:

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

var list = CreateList(o, o1);

Masz pomysł:)

 447
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 22:12:18

Oto odpowiedź.

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);
 112
Author: Dutt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 19:58:36

Istnieje wiele sposobów, aby to zrobić, ale niektóre z odpowiedzi tutaj tworzą listę, która zawiera elementy śmieci, co wymaga wyczyszczenia listy.

Jeśli szukasz pustej listy typu generic, użyj Select przeciwko liście krotek, aby utworzyć pustą listę. Żadne elementy nie zostaną utworzone.

Oto jednolinijkowy, aby utworzyć pustą listę:

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

Następnie możesz dodać do niej swój typ generyczny:

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

Jako alternatywę, możesz zrób coś takiego jak poniżej, aby utworzyć pustą listę (ale wolę pierwszy przykład, ponieważ możesz go użyć do wypełnionej kolekcji krotek):

 var emptyList = new List<object>()
          .Select(t => new { Id = default(int), Name = default(string) }).ToList();   
 67
Author: Paul Rouleau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-26 17:21:24

Nie do końca, ale możesz powiedzieć {[0] } i wszystko się ułoży. Jednak list[0].Id nie zadziała.

To będzie działać w czasie wykonywania W C# 4.0 przez posiadanie List<dynamic>, czyli nie dostaniesz IntelliSense.

 48
Author: Jeff Moser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-27 10:46:11

Chyba

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

void something() {
    var o = new { Id = 1, Name = "foo" };
    var emptyListOfAnonymousType = CreateEmptyGenericList(o);
}
Zadziała. Możesz też rozważyć napisanie tego w ten sposób:
void something() {
    var String = string.Emtpy;
    var Integer = int.MinValue;
    var emptyListOfAnonymousType = CreateEmptyGenericList(new { Id = Integer, Name = String });
}
 24
Author: erikkallen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-04 18:23:22

Zwykle używam następujących; głównie dlatego, że "zaczynasz" z listą, która jest pusta.

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

Ostatnio pisałem to tak:

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

Użycie metody repeat umożliwi również wykonanie:

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

..co daje początkową listę z pierwszym elementem już dodanym.

 22
Author: Rostov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-11 16:32:47

Możesz to zrobić w swoim kodzie.

var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });
 20
Author: MalachiteBR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-13 11:52:21

W najnowszej wersji 4.0, można używać dynamicznych jak poniżej

var list = new List<dynamic>();
        list.Add(new {
            Name = "Damith"
    });
        foreach(var item in list){
            Console.WriteLine(item.Name);
        }
    }
 13
Author: Damith Asanka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-31 09:31:45

Sprawdziłem IL na kilka odpowiedzi. Ten kod efektywnie dostarcza pustą listę:

    using System.Linq;
    …
    var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();
 11
Author: MEC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-04 18:03:25

Jeśli używasz C# 7 lub nowszego, możesz użyć tuple types zamiast anonimowych typów.

var myList = new List<(int IntProp, string StrProp)>();
myList.Add((IntProp: 123, StrProp: "XYZ"));
 10
Author: Bassem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-31 04:57:03

Możesz utworzyć listę dynamicznych.

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

"dynamic" jest inicjalizowane przez pierwszą wartość dodaną.

 9
Author: Code Name Jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-26 18:40:00

Oto moja próba.

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

Wpadłem na to, gdy napisałem coś podobnego do tworzenia anonimowej listy dla niestandardowego typu.

 8
Author: user_v,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-07 11:11:51

Oto kolejna metoda tworzenia listy anonimowych typów, która pozwala zacząć od pustej listy, ale nadal mieć dostęp do IntelliSense.

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

Jeśli chcesz zachować pierwszy element, po prostu umieść jedną literę w łańcuchu.

var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();
 7
Author: Brackus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-12 22:13:48

Zamiast tego:

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);
Możesz to zrobić:
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);

Jednak, jeśli spróbujesz zrobić coś takiego w innym zakresie, otrzymasz błąd kompilacji, chociaż działa to w czasie wykonywania:

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

Problem polega na tym, że tylko członkowie obiektu są dostępne w czasie wykonywania, chociaż intellisense wyświetli właściwości id i name.

W. Net 4.0 rozwiązaniem jest użycie w kodzie słowa kluczowego dynamic iste of object powyżej.

Innym rozwiązaniem jest użycie odbicia, aby uzyskać właściwości

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();
        }
    }
}
 6
Author: Jakob Flygare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 20:03:04

Jestem bardzo zaskoczony, że nikt nie zasugerował inicjalizacji kolekcji. W ten sposób można dodawać obiekty tylko wtedy, gdy lista jest tworzona stąd nazwa, jednak wydaje się, że jest to najładniejszy sposób. Nie ma potrzeby tworzenia tablicy, a następnie konwertowania jej na listę.

var list = new List<dynamic>() 
{ 
    new { Id = 1, Name = "Foo" }, 
    new { Id = 2, Name = "Bar" } 
};

Zawsze możesz użyć object zamiast dynamic, ale próba zachowania tego w prawdziwy ogólny sposób wtedy dynamic ma większy sens.

 6
Author: Tom Dee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-09 20:23:02

Możesz to zrobić w ten sposób:

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

Wydaje mi się to trochę "hacky", ale działa - jeśli naprawdę potrzebujesz listy i nie możesz po prostu użyć anonimowej tablicy.

 5
Author: Jermismo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-04 22:47:51
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);
 5
Author: morlock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-02 10:20:48

To stare pytanie, ale pomyślałem, że wstawię odpowiedź w C # 6. Często muszę skonfigurować dane testowe, które można łatwo wprowadzić w kodzie jako listę krotek. Dzięki kilku funkcjom rozszerzenia możliwe jest posiadanie tego ładnego, kompaktowego formatu, bez powtarzania nazw na każdym wpisie.

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

To daje liczbę mnogą-jeśli chcesz listę, do której możesz dodać, po prostu dodaj tolist ().

Magia pochodzi z niestandardowych metod dodawania rozszerzeń dla krotek, opisanych na 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...

}

Jedyną rzeczą, której nie lubię, jest to, że typy są oddzielone od nazw, ale jeśli naprawdę nie chcesz tworzyć nowej klasy, to takie podejście nadal pozwoli Ci mieć czytelne dane.

 5
Author: Peter Davidson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:17

W drugim przykładzie, w którym musisz zainicjować nową List<T>, jednym z pomysłów jest utworzenie anonimowej listy, a następnie jej wyczyszczenie.

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

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

Lub jako metoda rozszerzenia, powinna być łatwiejsza:

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

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

Lub prawdopodobnie jeszcze krótszy,

var list = new int[0].Select(x => new { Id = 0, Name = "" }).Tolist();
 3
Author: nawfal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-30 03:23:05

Wychodząc z tej odpowiedzi , wymyśliłem dwie metody, które mogłyby wykonać to zadanie:

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

Możesz użyć metod takich jak

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

Ta odpowiedź ma podobny pomysł, ale nie widziałem go, dopóki nie stworzyłem tych metod.

 1
Author: BrainStorm.exe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-12 20:05:25

Spróbuj z tym:

var result = new List<object>();

foreach (var test in model.ToList()) {
   result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}
 0
Author: Matteo Gariglio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-24 11:23:08
static void Main()
{
    List<int> list = new List<int>();
    list.Add(2);
    list.Add(3);
    list.Add(5);
    list.Add(7);
}
 -14
Author: Ravi Saini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 13:47:36