Общий список анонимного класса

В С# 3.0 вы можете создать анонимный класс со следующим синтаксисом

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

Есть ли способ добавить этот анонимный класс в общий список?

Пример:

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

Другой пример:

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

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

Ответ 1

Вы можете сделать:

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

Существует множество способов скинирования этой кошки, но в основном они все будут использовать вывод типа где-то - это означает, что вы должны называть общий метод (возможно, как метод расширения). Другим примером может быть:

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

var list = CreateList(o, o1);

Вы получаете идею:)

Ответ 2

Вот ответ.

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

Ответ 3

Существует много способов сделать это, но некоторые из ответов здесь создают список, содержащий элементы мусора, для которого требуется очистить список.

Если вы ищете пустой список общего типа, используйте "Выбрать против списка кортежей", чтобы создать пустой список. Никакие элементы не будут созданы.

Здесь однострочный файл для создания пустого списка:

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

Затем вы можете добавить к нему свой общий тип:

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

В качестве альтернативы вы можете сделать что-то вроде ниже, чтобы создать пустой список (но, я предпочитаю первый пример, потому что вы можете использовать его для заполненной коллекции Tuples):

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

Ответ 4

Не совсем, но вы можете сказать List<object>, и все будет работать. Однако list[0].Id не будет работать.

Это будет работать во время выполнения в С# 4.0 с помощью List<dynamic>, то есть вы не получите IntelliSense.

Ответ 5

Думаю,

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

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

будет работать.

Вы также можете подумать о том, чтобы написать его следующим образом:

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

Ответ 6

Обычно я использую следующее: главным образом потому, что вы "начинаете" с пустого списка.

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

В последнее время я писал это так:

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

Использование метода повторения также позволит вам:

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

.., который дает вам начальный список с первым добавленным элементом.

Ответ 7

Вы можете сделать это в своем коде.

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

Ответ 8

Я проверил IL на несколько ответов. Этот код эффективно предоставляет пустой список:

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

Ответ 9

В последней версии 4.0 можно использовать динамический, как показано ниже

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

Ответ 10

Вот моя попытка.

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

Я придумал это, когда написал что-то подобное для создания анонимного списка для настраиваемого типа.

Ответ 11

Вот еще один способ создания списка анонимных типов, который позволяет начать с пустого списка, но все же иметь доступ к IntelliSense.

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

Если вы хотите сохранить первый элемент, просто поместите одну строку в строку.

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

Ответ 12

Вы можете создать динамический список.

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

"динамический" инициализируется первым добавленным значением.

Ответ 13

Вместо этого:

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

Вы можете сделать это:

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

Однако вы получите компиляционную ошибку, если попытаетесь сделать что-то подобное в другой области, хотя она работает во время выполнения:

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

Проблема заключается в том, что во время выполнения доступны только члены Object, хотя intellisense будет показывать свойства id и имя.

В .net 4.0 решение должно использовать ключевое слово динамическое istead объекта в приведенном выше коде.

Другим решением является использование отражения для получения свойств

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

Ответ 14

var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);

Ответ 15

Это старый вопрос, но я думал, что поставлю свой ответ на С# 6. Мне часто приходится настраивать тестовые данные, которые легко ввести в код в виде списка кортежей. Имея пару функций расширения, возможно иметь этот красивый компактный формат, не повторяя имена каждой записи.

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

Это дает IEnumerable - если вам нужен список, который вы можете добавить, а затем просто добавить ToList().

Магия исходит из пользовательского расширения. Добавьте методы для кортежей, как описано в fooobar.com/questions/20504/....

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

}

Единственное, что мне не нравится, это то, что типы отделяются от имен, но если вы действительно не хотите создавать новый класс, этот подход все равно позволит вам иметь доступные для чтения данные.

Ответ 16

Вы можете сделать это следующим образом:

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

Мне кажется немного "взломанным", но он работает - если вам действительно нужен список и не может просто использовать анонимный массив.

Ответ 17

Для вашего второго примера, когда вы должны инициализировать новый List<T>, одна идея состоит в создании анонимного списка, а затем его очистке.

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

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

Или как метод расширения, должно быть проще:

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

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

Или, возможно, даже короче,

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

Ответ 18

Исходя из этого ответа, я придумал два метода, которые могли бы выполнить задачу:

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

Вы можете использовать такие методы, как

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

У этого ответа есть похожая идея, но я не видел ее до тех пор, пока не применил эти методы.

Ответ 19

Попробуйте следующее:

var result = new List<object>();

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

Ответ 20

Я очень удивлен, что никто не предложил инициализаторы коллекции. Таким способом можно добавлять объекты только тогда, когда список создан, отсюда и название, однако это кажется наилучшим способом сделать это. Нет необходимости создавать массив, а затем преобразовывать его в список.

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

Вы всегда можете использовать object вместо dynamic, но попытка сохранить его в действительно общем виде, тогда dynamic имеет больше смысла.

Ответ 21

static void Main()
{
    List<int> list = new List<int>();
    list.Add(2);
    list.Add(3);
    list.Add(5);
    list.Add(7);
}