2009-03-04 89 views
329

的泛型列表在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}); 
    .... 
} 
+1

请注意,所有对象必须在数组中输入相同。很少你可能需要帮忙演员,尤其是对于nulls new [] {new {Id =(int?)null,Name =“Foo”},new {Id =(int?)1,Name =“Foo” }}` – AaronLS 2013-05-24 19:25:11

+1

匿名类型被设计为用作临时存储,在大多数情况下,您可以使用Select(i => new {i.ID,i.Name})在LINQ select语句中创建它们;如果您将while子句重新定义为LINQ.Where语句,您将不需要该列表,并且如果您确实可以直接调用ToList,则它将返回正确类型的IEnumerable。 – MikeT 2014-11-27 11:00:54

回答

349

你可以这样做:

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

你的想法:)

+0

正确的语法(至少在3.5)是var list = new [] {o,o1}; – DHornpout 2009-03-04 22:43:21

+27

@DHornpout:这将给出一个数组,而不是一个列表。 – 2009-03-04 22:47:05

+1

你使用的是什么版本?这是我得到的编译器错误 错误'System.Array'不包含'ToList'的定义,并且没有找到接受'System.Array'类型的第一个参数的扩展方法'ToList'你错过了使用指令或程序集引用?) – DHornpout 2009-03-04 22:52:18

37

不完全是,但你能说List<object>事情会工作。但是,list[0].Id将不起作用。

这将工作在运行时在C#4.0中有一个List<dynamic>,这是你不会得到智能感知。

+0

虽然它不是强类型,从这个意义上说,你将不会有对列表中项目的编译器智能感知支持。 – 2009-03-04 22:12:18

+22

这是我害怕人们会用动态做的事情。 – erikkallen 2009-03-05 09:47:45

+1

我没有说这是一个伟大的想法,但它有可能:-)例如,如果从Ruby存储对象,可能有需要。 – 2009-03-05 14:40:13

21

我猜

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

你可以这样来做:

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

似乎有点“哈克”对我来说,但它的作品 - 如果你真的需要有一个列表,不能只使用匿名数组。

84

这是答案。

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

取而代之的是:

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名称

In .net 4。0解决方案是在上面的代码中使用关键字动态 is 对象

另一种解决方案是使用反射来获取属性

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

这里是我的尝试。

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

我想出了这个,当我写了一个类似的做一个自定义类型的匿名列表。

5
var list = new[]{ 
new{ 
FirstField = default(string), 
SecondField = default(int), 
ThirdField = default(double) 
} 
}.ToList(); 
list.RemoveAt(0); 
-11
static void Main() 
{ 
    List<int> list = new List<int>(); 
    list.Add(2); 
    list.Add(3); 
    list.Add(5); 
    list.Add(7); 
} 
17

你可以在你的代码做到这一点。

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

为了您的第二个例子,在那里你必须初始化一个新的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(); 
15

我通常使用以下;主要是因为你随后用一个空的列表“开始”。

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

..这给你初始列表中已添加第一个项目。

0

尝试这样的:

var result = new List<object>(); 

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

这里是一个创建匿名类型的列表,让您开始与一个空表的另一种方法,但仍然可以访问智能感知。

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

如果您想保留第一项,只需在字符串中放置一个字母。

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

有很多方法可以做到这一点,但这里的一些响应是创建一个包含垃圾元素的列表,这需要您清除列表。

如果您正在查找泛型类型的空列表,请使用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(); 
7

我在几个答案中检查了IL。此代码有效地提供了一个空列表:

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

这是一个老问题,但我想我会把我的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... 

}

我不喜欢的唯一的事情是,类型从名字分开了,但如果你真的不想做一个新的类,那么这种做法将仍然让你有可读的数据。

3

在最新的4.0版,可以使用动态象下面

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

您可以创建动态列表。

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

“dynamic”被第一个增加的值初始化。