Вопрос

В C # 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});
    ....
}
Это было полезно?

Решение

Вы могли бы сделать:

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

Вы поняли идею :)

Другие советы

Вот и весь ответ.

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

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

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

Вот однострочник для создания пустого списка:

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

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

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

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

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

Я думаю

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

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

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

Использование метода repeat также позволило бы вам сделать:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 решение заключается в использовании ключевого слова динамичный истеад из объект в приведенном выше коде.

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

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

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

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

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

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

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

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

Это старый вопрос, но я подумал, что вставлю свой ответ на C # 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().

Волшебство исходит от пользовательских методов добавления расширений для кортежей, как описано в 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...

}

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

Для вашего второго примера, где вам нужно инициализировать новый 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();

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

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

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

Попробуйте с этим:

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);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top