時々、タプルを使用する必要があります。たとえば、タンクとそのターゲットタンクのリストがあります(それらは、それらのようなものを追跡します)。
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);
もちろん、定義するときにリストに渡すタイプがないという問題
匿名型の空のリストを作成して使用し、完全なインテリセンスとコンパイル時のチェックを楽しむことができます。
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);
List<dynamic>
を使用できます。
var myList = new List<dynamic>();
myList.Add(new {Tank = new Tank(), AttackingTank = new Tank()});
Console.WriteLine("AttackingTank: {0}", myList[0].AttackingTank);
ハックは次のとおりです。
_var myList = Enumerable.Empty<int>()
.Select(dummy => new { AttackingTank = default(Tank), TargetTank = default(Tank), })
.ToList();
_
Tank
がクラス型の場合、default(Tank)
の代わりに_(Tank)null
_と書くことができます。また、手元にある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), });
_
最後に、このような構文を使用する可能性があることに注意する価値があります。 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;
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}
);
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);
またはさらにシンプル
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();
静的機能を失います。
ここにもう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) });
オブジェクトのリストを作成できます:
List<object> myList = new List<object>();
次に、匿名タイプをリストに追加します。
myList.Add(new {Name = "me", phone = 123});