是否有创建匿名类型的通用列表中招?(Is there a trick in creating a generic list of anonymous type?)

有时候,我需要使用一个元组,例如我有坦克和他们的目标坦克的名单(他们之后他们或类似的东西追逐):

List<Tuple<Tank,Tank>> mylist = new List<Tuple<Tank,Tank>>();

然后当我遍历列表我通过访问它们

mylist[i].item1 ...
mylist[i].item2 ...

这是非常混乱,我总是忘了是什么物品1,什么是项目2,如果我可以通过访问它们:

mylist[i].AttackingTank...
mylist[i].TargetTank...

这将是更加清晰,有没有办法做到这一点不定义一个类:

MyTuple
{
public Tank AttackingTank;
public Tank TargetTank;
}

我想避免这种定义类,因为那样我会在不同的场景来定义许多不同的类,我可以做一些“绝招”,使这个匿名。

就像是 :

var k = new {Name = "me", phone = 123};
mylist.Add(k);

我没有一个类型的课程的问题传递到列表时,我把它定义

Answer 1:

您可以创建匿名类型的空列表,然后使用它,享受完整的intellisense和编译时检查:

var list = Enumerable.Empty<object>()
             .Select(r => new {A = 0, B = 0}) // prototype of anonymous type
             .ToList();

list.Add(new { A = 4, B = 5 }); // adding actual values

Console.Write(list[0].A);


Answer 2:

你可以使用一个List<dynamic>

 var myList = new List<dynamic>();
 myList.Add(new {Tank = new Tank(), AttackingTank = new Tank()});

 Console.WriteLine("AttackingTank: {0}", myList[0].AttackingTank);


Answer 3:

这里是一个黑客:

var myList = Enumerable.Empty<int>()
    .Select(dummy => new { AttackingTank = default(Tank), TargetTank = default(Tank), })
    .ToList();

如果Tank是一个类类型,你可以写(Tank)null的,而不是default(Tank) 。 你也可以使用一些Tank你碰巧手边实例。


编辑:

要么:

var myList = Enumerable.Repeat(
    new { AttackingTank = default(Tank), TargetTank = default(Tank), },
    0).ToList();

如果你犯了一个通用的方法,你将不必使用Enumerable.Empty 。 这可能是这样的:

static List<TAnon> GetEmptyListWithAnonType<TAnon>(TAnon dummyParameter)
{
    return new List<TAnon>();
}

这是被称为与TAnon从使用中推断出来的,当然,如:

var myList = GetEmptyListWithAnonType(new { AttackingTank = default(Tank), TargetTank = default(Tank), });


Answer 4:

这是值得大家注意的最后,有可能使用这样的语法。 它在C#7.0中引入

var tanks = new List<(Tank AttackingTank, Tank TargetTank)>();

(Tank, Tank) tTank = (new Tank(), new Tank());
tanks.Add(tTank);

var a = tanks[0].AttackingTank;
var b = tanks[0].TargetTank;


Answer 5:

你可以只是采用一个通用的方法params并返回它:

public static IList<T> ToAnonymousList<T>(params T[] items)
{
  return items;
}

所以,现在你可以说:

var list=ToAnonymousList
(
  new{A=1, B=2},
  new{A=2, B=2}
);


Answer 6:

如何ExpandoObject

dynamic tuple = new ExpandoObject(); 
tuple.WhatEverYouWantTypeOfTank = new Tank(); // Value of any type

EDITS:

dynamic tuple = new ExpandoObject();
tuple.AttackingTank = new Tank();
tuple.TargetTank = new Tank();

var mylist = new List<dynamic> { tuple };

//access to items
Console.WriteLine(mylist[0].AttackingTank);


Answer 7:

或者更简单

        var tupleList = (
           new[] {
                new { fruit = "Tomato", colour = "red"},
                new { fruit = "Tomato", colour = "yellow"},
                new { fruit = "Apple", colour = "red"},
                new { fruit = "Apple", colour = "green"},
                new { fruit = "Medlar", colour = "russet"}
            }).ToList();

其失去静电功能。



Answer 8:

只是在这里添加一个更加得心应手一点。 我使用场合Alex的答案,但它使我有点疲于跟踪它背下来,当我需要它,因为它不是很明显(我发现自己寻找“新{”)。

所以我加了下面的小静态方法(我希望我可以使它的扩展方法,但什么类型的?):

public static List<T> CreateEmptyListOf<T>(Func<T> itemCreator)
{
    return Enumerable
        .Empty<object>()
        .Select(o => itemCreator())
        .ToList();
}

这种隔离每个我需要从那些同这种模式的时间是不同的部分。 我这样称呼它:

var emptyList = Ext.CreateEmptyListOf(() => new { Name = default(string), SomeInt = default(int) });


Answer 9:

您可以创建对象的列表:

List<object> myList = new List<object>();

然后匿名类型添加到列表:

myList.Add(new {Name = "me", phone = 123});