web-dev-qa-db-ja.com

匿名型の一般的なリストを作成するトリックはありますか?

時々、タプルを使用する必要があります。たとえば、タンクとそのターゲットタンクのリストがあります(それらは、それらのようなものを追跡します)。

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

もちろん、定義するときにリストに渡すタイプがないという問題

37
OopsUser

匿名型の空のリストを作成して使用し、完全なインテリセンスとコンパイル時のチェックを楽しむことができます。

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

List<dynamic>を使用できます。

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

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

ハックは次のとおりです。

_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), });
_
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;
7
Puchacz

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
Sean

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

またはさらにシンプル

        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

ここにもう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) });
1
rrreee

オブジェクトのリストを作成できます:

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

次に、匿名タイプをリストに追加します。

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