it-swarm.com.de

Eine generische Liste anonymer Klassen

In C # 3.0 können Sie anonyme Klassen mit der folgenden Syntax erstellen

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

Gibt es eine Möglichkeit, diese anonyme Klasse zu einer generischen Liste hinzuzufügen?

Beispiel:

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

Ein anderes Beispiel:

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

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}
366
DHornpout

Du könntest es tun:

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

Es gibt viele Möglichkeiten, diese Katze zu enthäuten, aber im Grunde werden sie alle irgendwo Typinferenz verwenden - was bedeutet, dass Sie eine generische Methode aufrufen müssen (möglicherweise als Erweiterungsmethode). Ein anderes Beispiel könnte sein:

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

var list = CreateList(o, o1);

Du hast die Idee :)

386
Jon Skeet

Hier ist die Antwort.

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

Es gibt viele Möglichkeiten, dies zu tun, aber bei einigen Antworten wird eine Liste erstellt, die Müllelemente enthält. Hierfür müssen Sie die Liste löschen. 

Wenn Sie nach einer leeren Liste des generischen Typs suchen, verwenden Sie Auswählen gegen eine Liste von Tupeln, um die leere Liste zu erstellen. Es werden keine Elemente instanziiert.

Hier ist der One-Liner zum Erstellen einer leeren Liste:

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

Dann können Sie es mit Ihrem generischen Typ hinzufügen:

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

Als Alternative können Sie wie folgt vorgehen, um die leere Liste zu erstellen (Ich bevorzuge jedoch das erste Beispiel, da Sie es auch für eine besetzte Sammlung von Tupeln verwenden können):

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

Nicht genau, aber Sie können List<object> sagen und die Dinge funktionieren. list[0].Id funktioniert jedoch nicht. 

Dies funktioniert zur Laufzeit in C # 4.0 durch einen List<dynamic>, das heißt, Sie erhalten IntelliSense nicht. 

41
Jeff Moser

Ich vermute

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

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

wird funktionieren.

Sie könnten es auch in Betracht ziehen, es so zu schreiben:

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

Sie können dies in Ihrem Code tun.

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

Ich verwende normalerweise Folgendes: hauptsächlich, weil Sie dann mit einer leeren Liste "beginnen".

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

In letzter Zeit habe ich stattdessen so geschrieben:

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

Mit der Wiederholungsmethode können Sie auch Folgendes tun:

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

..was gibt Ihnen die ursprüngliche Liste mit dem ersten bereits hinzugefügten Element.

18
Rostov

Ich habe die IL auf mehrere Antworten geprüft. Dieser Code stellt effizient eine leere Liste bereit:

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

In der neuesten Version 4.0 können Sie Dynamiken wie folgt verwenden

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

Hier ist mein Versuch.

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

Ich kam dazu, als ich etwas Ähnliches für das Erstellen einer anonymen Liste für einen benutzerdefinierten Typ schrieb.

7
user_v

Hier ist eine weitere Methode zum Erstellen einer Liste anonymer Typen, mit der Sie mit einer leeren Liste beginnen können, aber trotzdem auf IntelliSense zugreifen können.

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

Wenn Sie das erste Element behalten möchten, geben Sie einfach einen Buchstaben in die Zeichenfolge ein.

var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();
6
Brackus
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);
5
morlock

An Stelle von:

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

Sie könnten das tun:

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

Wenn Sie versuchen, in einem anderen Bereich so etwas zu tun, wird jedoch ein Compiletime-Fehler angezeigt, obwohl dies zur Laufzeit funktioniert:

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

Das Problem ist, dass nur die Member von Object zur Laufzeit verfügbar sind, obwohl Intellisense die Eigenschaften id und name anzeigt.

In .net 4.0 besteht die Lösung darin, das Schlüsselwort dynamic istead von object im obigen Code zu verwenden.

Eine andere Lösung ist die Verwendung der Reflektion, um die Eigenschaften zu erhalten

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();
        }
    }
}
5
Jakob Flygare

Für das zweite Beispiel, bei dem Sie einen neuen List<T> initialisieren müssen, besteht eine Idee darin, eine anonyme Liste zu erstellen und sie anschließend zu löschen.

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

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

Oder als Erweiterungsmethode sollte es einfacher sein:

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

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

Oder wahrscheinlich noch kürzer

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

Dies ist eine alte Frage, aber ich dachte, ich würde meine C # 6-Antwort einfügen. Ich muss oft Testdaten einrichten, die einfach als eine Liste von Tupeln in den Code eingegeben werden. Mit einigen Erweiterungsfunktionen ist es möglich, dieses schöne, kompakte Format zu verwenden, ohne die Namen jedes Eintrags zu wiederholen.

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

Dies gibt ein IEnumerable - wenn Sie eine Liste möchten, die Sie hinzufügen können, fügen Sie einfach ToList () hinzu.

Die Magie kommt von der benutzerdefinierten Erweiterung Fügen Sie Methoden für Tupel hinzu, wie unter https://stackoverflow.com/a/27455822/4536527 beschrieben.

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...

}

Das einzige, was mir nicht gefällt, ist, dass die Typen von den Namen getrennt sind. Wenn Sie jedoch wirklich keine neue Klasse erstellen möchten, können Sie mit diesem Ansatz trotzdem lesbare Daten erhalten.

3
Peter Davidson

Sie können eine dynamische Liste erstellen.

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

"dynamisch" wird durch die erste Wertschöpfung initialisiert. 

3
Code Name Jack

Sie können es so machen:

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

Es erscheint mir etwas "hackig", aber es funktioniert - wenn Sie wirklich eine Liste benötigen und das anonyme Array nicht verwenden können.

2
Jermismo

Versuchen Sie es damit: 

var result = new List<object>();

foreach (var test in model.ToList()) {
   result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}
0
Matteo Gariglio

Abgeleitet von dieser Antwort habe ich zwei Methoden gefunden, die die Aufgabe erfüllen könnten:

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

Sie können die Methoden wie verwenden

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

Diese Antwort hat eine ähnliche Idee, aber ich habe sie erst gesehen, nachdem ich diese Methoden gemacht habe.

0
BrainStorm.exe