40

有时我需要使用元组,例如我有坦克列表和他们的目标坦克(他们追逐他们或类似的东西):

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

4

9 回答 9

99

您可以为匿名类型创建一个空列表,然后使用它,享受完整的智能感知和编译时检查:

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);
于 2013-04-01T18:59:20.190 回答
18

你可以使用一个List<dynamic>.

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

 Console.WriteLine("AttackingTank: {0}", myList[0].AttackingTank);
于 2013-04-01T18:41:33.340 回答
8

这是一个黑客:

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), });
于 2013-04-01T19:05:38.317 回答
8

值得注意的是,最后,有可能使用这样的语法。它已在 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;
于 2017-11-08T13:00:07.847 回答
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}
);
于 2015-06-09T15:58:13.203 回答
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);
于 2013-04-01T18:49:50.890 回答
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();

这失去了静态功能。

于 2016-04-20T08:41:56.437 回答
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) });
于 2016-06-21T14:45:27.283 回答
0

您可以创建对象列表:

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

然后将匿名类型添加到您的列表中:

myList.Add(new {Name = "me", phone = 123});
于 2018-05-17T17:29:50.267 回答