有时我需要使用一个元组,例如我有坦克和他们的目标坦克列表(他们追逐他们或类似的东西):
List<Tuple<Tank,Tank>> mylist = new List<Tuple<Tank,Tank>>();
然后当我遍历列表时,我通过
访问它们mylist[i].item1 ...
mylist[i].item2 ...
这非常令人困惑,我总是忘记什么是item1,什么是item2,如果我可以通过以下方式访问它们:
mylist[i].AttackingTank...
mylist[i].TargetTank...
它会更清楚,有没有办法在没有定义类的情况下完成它:
MyTuple
{
public Tank AttackingTank;
public Tank TargetTank;
}
我想避免定义这个类,因为那时我必须在不同的场景中定义许多不同的类,我可以做一些“技巧”并使这个匿名。
类似的东西:
var k = new {Name = "me", phone = 123};
mylist.Add(k);
当然,我定义它时没有类型传递给List的问题
答案 0 :(得分:92)
您可以为匿名类型创建一个空列表,然后使用它,享受完整的智能感知和编译时检查:
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);
答案 1 :(得分:17)
您可以使用List<dynamic>
。
var myList = new List<dynamic>();
myList.Add(new {Tank = new Tank(), AttackingTank = new Tank()});
Console.WriteLine("AttackingTank: {0}", myList[0].AttackingTank);
答案 2 :(得分:7)
这是一个黑客:
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), });
答案 3 :(得分:7)
值得注意的是,最后,有可能使用这样的语法。它已在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;
答案 4 :(得分: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}
);
答案 5 :(得分:2)
ExpandoObject怎么样?
dynamic tuple = new ExpandoObject();
tuple.WhatEverYouWantTypeOfTank = new Tank(); // Value of any type
<强>编辑:强>
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);
答案 6 :(得分:1)
甚至更简单
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();
失去了静态功能。
答案 7 :(得分:1)
在这里添加一个方便的位。我偶尔会使用亚历克斯的答案,但是当我需要它时,它会让我有点疯狂地尝试追踪它,因为它并不明显(我发现自己正在寻找“新{”)。
所以我添加了以下一些静态方法(我希望我可以使它成为一个扩展方法,但是它的类型是什么?):
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) });
答案 8 :(得分:0)
您可以创建对象列表:
List<object> myList = new List<object>();
然后将匿名类型添加到您的列表中:
myList.Add(new {Name = "me", phone = 123});