web-dev-qa-db-fra.com

Une liste générique de classe anonyme

En C # 3.0, vous pouvez créer une classe anonyme avec la syntaxe suivante

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

Est-il possible d'ajouter ces classes anonymes à une liste générique?

Exemple:

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 autre exemple:

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

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

Vous pourriez faire:

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

Il existe de nombreuses façons de dépouiller ce chat, mais fondamentalement, ils utiliseront tous l'inférence de type quelque part - ce qui signifie que vous devez appeler une méthode générique (éventuellement en tant que méthode d'extension). Un autre exemple pourrait être:

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

var list = CreateList(o, o1);

Vous avez eu l'idée :)

386
Jon Skeet

Voici la réponse.

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

Il existe plusieurs façons de procéder, mais certaines des réponses présentées ici créent une liste contenant des éléments parasites, ce qui vous oblige à effacer la liste. 

Si vous recherchez une liste vide du type générique, utilisez un bouton Sélectionner contre une liste de nuplets pour créer la liste vide. Aucun élément ne sera instancié.

Voici le one-liner pour créer une liste vide:

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

Ensuite, vous pouvez y ajouter en utilisant votre type générique:

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

Comme alternative, vous pouvez faire quelque chose comme ci-dessous pour créer la liste vide (mais je préfère le premier exemple car vous pouvez également l'utiliser pour une collection remplie de Tuples):

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

Pas exactement, mais vous pouvez dire List<object> et tout ira bien. Cependant, list[0].Id ne fonctionnera pas. 

Cela fonctionnera au moment de l'exécution en C # 4.0 en ayant un List<dynamic>, c'est-à-dire que vous n'obtiendrez pas IntelliSense. 

41
Jeff Moser

Je suppose

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

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

marchera.

Vous pourriez aussi envisager de l'écrire comme ceci:

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

Vous pouvez le faire dans votre code.

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

J'utilise habituellement ce qui suit. principalement parce que vous «démarrez» alors avec une liste vide.

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

Dernièrement, je l'ai écrit comme ceci à la place:

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

L'utilisation de la méthode repeat vous permettrait également de:

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

..qui vous donne la liste initiale avec le premier élément déjà ajouté.

18
Rostov

J'ai vérifié le IL sur plusieurs réponses. Ce code fournit efficacement une liste vide:

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

Dans la dernière version 4.0, pouvez utiliser dynamique comme ci-dessous

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

Voici ma tentative.

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

Je suis arrivé à cela quand j'ai écrit quelque chose de similaire pour créer une liste anonyme pour un type personnalisé.

7
user_v

Voici une autre méthode de création d'une liste de types anonymes qui vous permet de commencer avec une liste vide, tout en ayant accès à IntelliSense.

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

Si vous souhaitez conserver le premier élément, il suffit de mettre une lettre dans la chaîne.

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

Au lieu de cela:

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

Vous pourriez faire ceci:

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

Cependant, vous obtiendrez une erreur de compilation si vous essayez de faire quelque chose comme ceci dans une autre portée, bien que cela fonctionne au moment de l'exécution:

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

Le problème est que seuls les membres de Object sont disponibles au moment de l’exécution, même si intellisense affiche les propriétés id et name .

Dans .net 4.0, une solution consiste à utiliser le mot-clé dynamic istead de object dans le code ci-dessus.

Une autre solution consiste à utiliser la réflexion pour obtenir les propriétés

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

Pour votre deuxième exemple, où vous devez initialiser un nouveau List<T>, une idée consiste à créer une liste anonyme, puis à la supprimer.

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

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

Ou comme une méthode d'extension, devrait être plus facile:

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 probablement même plus court,

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

C'est une vieille question, mais je pensais mettre ma réponse C # 6. Je dois souvent configurer des données de test qui sont facilement entrées dans le code sous forme de liste de n-uplets. Avec quelques fonctions d’extension, il est possible d’avoir ce format agréable et compact sans répéter les noms sur chaque entrée.

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

Cela donne un IEnumerable - si vous voulez une liste que vous pouvez ajouter, ajoutez simplement ToList ().

La magie vient de l'extension personnalisée Ajoutez des méthodes pour les n-uplets, comme décrit à 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...

}

La seule chose que je n'aime pas, c'est que les types sont séparés des noms, mais si vous ne voulez vraiment pas créer une nouvelle classe, cette approche vous laissera quand même des données lisibles.

3
Peter Davidson

Vous pouvez créer une liste de dynamique.

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

"dynamic" est initialisé par la première valeur ajoutée. 

3
Code Name Jack

Vous pouvez le faire de cette façon:

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

Cela me semble un peu "hacky", mais cela fonctionne - si vous avez vraiment besoin d'une liste et que vous ne pouvez pas simplement utiliser le tableau anonyme.

2
Jermismo

Essayez avec ceci: 

var result = new List<object>();

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

En dérivant de cette réponse , j'ai proposé deux méthodes pour effectuer cette tâche:

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

Vous pouvez utiliser les méthodes comme

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

Cette réponse a une idée similaire, mais je ne l'ai pas vue avant d'avoir fait ces méthodes.

0
BrainStorm.exe