匿名クラスの総称リスト


416

C#3.0では、次の構文で匿名クラスを作成できます

var o = new { Id = 1, Name = "Foo" };

これらの匿名クラスをジェネリックリストに追加する方法はありますか?

例:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

List<var> list = new List<var>();
list.Add(o);
list.Add(o1);

もう一つの例:

List<var> list = new List<var>();

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}

2
すべてのオブジェクトは配列内で同じように入力する必要があることに注意してください。まれに、特にnullの場合、キャストの支援が必要になることがありますnew[] { new{ Id = (int?)null, Name = "Foo" }, new { Id = (int?)1, Name = "Foo" }}
AaronLS 2013年

1
匿名型は一時記憶域として使用するように設計されており、ほとんどの場合、Select(i => new {i.ID、i.Name});を使用してLINQ selectステートメントで作成します。while句をLINQ.Whereステートメントに再定義すると、正しいタイプのIEnumerableが返されます。Whereステートメントではリストは必要ありません。そうした場合は、ToListを呼び出すだけです
MikeT

回答:


427

あなたがすることができます:

var list = new[] { o, o1 }.ToList();

この猫をスキニングする方法はたくさんありますが、基本的にはすべてどこかで型推論を使用します。つまり、ジェネリックメソッドを(おそらく拡張メソッドとして)呼び出す必要があります。別の例は次のとおりです。

public static List<T> CreateList<T>(params T[] elements)
{
     return new List<T>(elements);
}

var list = CreateList(o, o1);

あなたはアイデアを得ます:)


32
@DHornpout:これはList <T>ではなく配列になります。
ジョンスキート

23
@DHornpout:「using System.Linq;」を使用していますか?あなたのファイルの一番上に?ToListはLINQオペレーターです。
Jon Skeet、

5
了解しました。「System.Linqを使用」を含める必要があります。ありがとう。
DHornpout 2009年

2
Visual Studioでは一貫性がないように見えますが、参照された拡張メソッド(参照された型と同じ)を持つアセンブリの欠落したインクルードを見つけるのにIntelliSenseはあまり役に立ちません。
LOAS

3
この男はどこにでもいて、今日8つの質問を検索し、7つが彼によって回答されました。
Kugan Kumar

109

これが答えです。

string result = String.Empty;

var list = new[]
{ 
    new { Number = 10, Name = "Smith" },
    new { Number = 10, Name = "John" } 
}.ToList();

foreach (var item in list)
{
    result += String.Format("Name={0}, Number={1}\n", item.Name, item.Number);
}

MessageBox.Show(result);

12
ダット、あなたのコードは最後に.ToList()なしで動作するはずです。
DHornpout 2009年

3
いいですね。今度は、新しい{}行をselectステートメントで置き換える例が必要です。var list = sourceList.Select(o => new {o.ModelId、o.PartNumber、o.Quantity})。ToList();
topwik 2013年

@towpseそれに関する解決策はありますか?
Kiquenet 2013年

@ Dutt、List <T>を返すメソッド(関数)を使用する場合のサンプル?
Kiquenet 2013年

これでメソッドstring.Joinと文字列の補間ができるので、foreachおよびを使用する必要はありませんFormat
realsonic 2016

61

これを行うには多くの方法がありますが、ここでの応答の一部は、ガベージ要素を含むリストを作成しているため、リストをクリアする必要があります。

ジェネリック型の空のリストを探している場合は、タプルのリストに対する選択を使用して空のリストを作成します。要素はインスタンス化されません。

空のリストを作成するためのワンライナーは次のとおりです。

 var emptyList = new List<Tuple<int, string>>()
          .Select(t => new { Id = t.Item1, Name = t.Item2 }).ToList();

次に、ジェネリック型を使用してそれに追加できます。

 emptyList.Add(new { Id = 1, Name = "foo" });
 emptyList.Add(new { Id = 2, Name = "bar" });

別の方法として、以下のような方法で空のリストを作成することもできます(ただし、最初の例は、タプルのデータが入ったコレクションにも使用できるため、最初の例を好みます)。

 var emptyList = new List<object>()
          .Select(t => new { Id = default(int), Name = default(string) }).ToList();   

1
私はこの方法がとても好きです。ポールありがとう!タプルを使用できるのはいつでも良い日です!xD
ブレイディリレス2016年

私はこれが好き。私が渡すオブジェクトのある種の具体的な宣言があることは素晴らしいことです
。– Morvael

リストの時間を消去してコードを書き直すコードの記述を終了しました
JoshBerke

アイデアをありがとう。提案、使用する場合はダミーリストの割り当てを回避できますEnumerable.Empty<object>().Select(o=>definition).ToList()
BrainStorm.exe

45

正確ではありませんが、あなたは言うことができList<object>、物事はうまくいきます。ただし、機能しlist[0].Idません。

これは、C#4.0の実行時にを使用することで機能しますList<dynamic>。つまり、IntelliSenseを取得できません。


ただし、リスト内の項目に対するコンパイラのインテリセンスサポートがないという意味で、厳密に型指定されていません。
Joel Coehoorn 2009年

31
これは、人々がダイナミックでやることを恐れている種類のことです。
erikkallen 2009年

2
素晴らしいアイデアだとは言いませんでしたが、それは可能だったと思います:-)たとえば、Rubyからオブジェクトを保存する場合は、必要になる可能性があります。
Jeff Moser、

2
しかし、これらの場合、ソースタイプが動的であるため、匿名タイプにList <dynamic>を使用しても意味がありません。
Dykam 2009年

1
非常に役立ちます。特に、匿名のアイテムを追加する前にリストを定義する必要がある場合。
Karlth、2014

24

私は推測する

List<T> CreateEmptyGenericList<T>(T example) {
    return new List<T>();
}

void something() {
    var o = new { Id = 1, Name = "foo" };
    var emptyListOfAnonymousType = CreateEmptyGenericList(o);
}

働くでしょう。

次のように書くことも検討してください。

void something() {
    var String = string.Emtpy;
    var Integer = int.MinValue;
    var emptyListOfAnonymousType = CreateEmptyGenericList(new { Id = Integer, Name = String });
}

はい、このソリューションは、匿名配列の初期化を解決するのに役立ちます。ありがとう。
DHornpout 2009年

1
メソッド名の後に少し<T>を置くだけです。
マーティン

21

私は通常以下を使用します。主な理由は、空のリストから「開始」するためです。

var list = Enumerable.Range(0, 0).Select(e => new { ID = 1, Name = ""}).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );
//etc.

最近、代わりに次のように書いています。

var list = Enumerable.Repeat(new { ID = 1, Name = "" }, 0).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );

repeatメソッドを使用すると、次のことも可能になります。

var myObj = new { ID = 1, Name = "John" };
var list = Enumerable.Repeat(myObj, 1).ToList();
list.Add(new { ID = 2, Name = "Liana" });

..これにより、最初のアイテムが既に追加された初期リストが表示されます。


2
空のリストから始める必要はありません-Range(0,1)を実行し、selectステートメントの最初のオブジェクトを最初のオブジェクトにすることができます。
マシューM.

1
空のリストから始める必要はありません-(例のように)最初のアイテムが何であるかがわかっている場合は、コメントで正しいです。中間ファイル/データソースの解析にこれを使用し、LINQプロジェクションシナリオで使用するまで最初の真のアイテムにアクセスしません(したがって、最初のレコードのスキップを考慮する必要はありません)。
ロストフ

19

あなたのコードでこれを行うことができます。

var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });

11

最新バージョン4.0では、以下のようなダイナミックを使用できます

var list = new List<dynamic>();
        list.Add(new {
            Name = "Damith"
    });
        foreach(var item in list){
            Console.WriteLine(item.Name);
        }
    }

10

私はいくつかの回答でILをチェックしました。このコードは空のリストを効率的に提供します:

    using System.Linq;
    
    var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();

1
編集を拒否する理由はありますか?次の答えはを返しますIEnumerableが、私のバージョンはを返しますがList、OPが要求したとおりです。
Necronomicron、2015

私はこのアプローチを好む、あるいは近い1 この答えはnew object[] { }.Select(o => new { Id = default(int), Name = default(string) }).ToList()
palswim

8

これが私の試みです。

List<object> list = new List<object> { new { Id = 10, Name = "Testing1" }, new {Id =2, Name ="Testing2" }}; 

これを思いついたのは、カスタムタイプの匿名リストを作成するために同様のことを書いたときです。


8

動的のリストを作成できます。

List<dynamic> anons=new List<dynamic>();
foreach (Model model in models)
{
   var anon= new
   {
      Id = model.Id,
      Name=model.Name
   };
   anons.Add(anon);
}

「動的」は、追加された最初の値によって初期化されます。


7

これの代わりに:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List <var> list = new List<var>(); 
list.Add(o); 
list.Add(o1);

あなたはこれを行うことができます:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List<object> list = new List<object>(); 
list.Add(o); 
list.Add(o1);

ただし、実行時に機能しますが、別のスコープで次のようなことを実行しようとすると、コンパイル時エラーが発生します。

private List<object> GetList()
{ 
    List<object> list = new List<object>();
    var o = new { Id = 1, Name = "Foo" }; 
    var o1 = new { Id = 2, Name = "Bar" }; 
    list.Add(o); 
    list.Add(o1);
    return list;
}

private void WriteList()
{
    foreach (var item in GetList()) 
    { 
        Console.WriteLine("Name={0}{1}", item.Name, Environment.NewLine); 
    }
}

問題は、実行時にObjectのメンバーしか使用できないことですが、IntelliSenseはプロパティidnameを表示します。

.net 4.0での解決策は、上のコードでオブジェクトの代わりにキーワードdynamic i を使用することです。

別の解決策は、プロパティを取得するためにリフレクションを使用することです

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            var anonymous = p.GetList(new[]{
                new { Id = 1, Name = "Foo" },       
                new { Id = 2, Name = "Bar" }
            });

            p.WriteList(anonymous);
        }

        private List<T> GetList<T>(params T[] elements)
        {
            var a = TypeGenerator(elements);
            return a;
        }

        public static List<T> TypeGenerator<T>(T[] at)
        {
            return new List<T>(at);
        }

        private void WriteList<T>(List<T> elements)
        {
            PropertyInfo[] pi = typeof(T).GetProperties();
            foreach (var el in elements)
            {
                foreach (var p in pi)
                {
                    Console.WriteLine("{0}", p.GetValue(el, null));
                }
            }
            Console.ReadLine();
        }
    }
}

7

空のリストから始めて、IntelliSenseにアクセスできる匿名タイプのリストを作成する別の方法を次に示します。

var items = "".Select( t => new {Id = 1, Name = "foo"} ).ToList();

最初の項目を保持したい場合は、文字列に1文字を入れてください。

var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();

配列初期化子として文字列を使用することは機能するかもしれませんが、非常に悪い習慣です
MikeT

上記の回答のほとんどは特に「良い」実践ではありませんが、質問の性質上、これはある種の答えでした。匿名型は、このように機能するようには設計されていません。私の方法が他の方法よりも「悪い」のはなぜですか?何か足りないのですか?
Brackus 14

問題自体が悪い習慣を求めているので、あなたは正しいです。良い習慣の答えはありませんが、文字列を使用して文字の配列を生成し、それをユーザーが望むものの配列に変換しているためです。 、関係のないタイプであり、無駄なボクシングと非ボクシングの生成は効率的ではありません
MikeT

5
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);

5

これは古い質問ですが、C#6の回答を入れようと思いました。タプルのリストとしてコードに簡単に入力できるテストデータを設定する必要があることがよくあります。いくつかの拡張関数を使用すると、各エントリで名前を繰り返すことなく、この素敵でコンパクトな形式にすることができます。

var people= new List<Tuple<int, int, string>>() {
    {1, 11, "Adam"},
    {2, 22, "Bill"},
    {3, 33, "Carol"}
}.Select(t => new { Id = t.Item1, Age = t.Item2, Name = t.Item3 });

これにより、IEnumerableが提供されます。追加できるリストが必要な場合は、ToList()を追加するだけです。

魔法は、https: //stackoverflow.com/a/27455822/4536527で説明されているように、タプルのカスタム拡張Addメソッドから来ています

public static class TupleListExtensions    {
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
            T1 item1, T2 item2)       {
        list.Add(Tuple.Create(item1, item2));
    }

    public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
            T1 item1, T2 item2, T3 item3) {
        list.Add(Tuple.Create(item1, item2, item3));
    }

// and so on...

}

私が気に入らない唯一のことは、型が名前から分離されていることですが、本当に新しいクラスを作成したくない場合は、このアプローチでも読み取り可能なデータを使用できます。


4

誰もコレクション初期化子を提案していないことにとても驚いています。この方法では、リストが作成されたときにのみオブジェクトを追加できるため、名前が付けられますが、これが最も良い方法のようです。配列を作成してリストに変換する必要はありません。

var list = new List<dynamic>() 
{ 
    new { Id = 1, Name = "Foo" }, 
    new { Id = 2, Name = "Bar" } 
};

object代わりにいつでも使用できますがdynamic、それを本当の一般的な方法で維持しようとすることは、dynamicより理にかなっています。


3

あなたはこの方法でそれを行うことができます:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

var array = new[] { o, o1 };
var list = array.ToList();

list.Add(new { Id = 3, Name = "Yeah" });

私には少し「ハッキー」に思えますが、それは機能します-リストが本当に必要であり、匿名配列だけを使用できない場合。


3

2番目の例では、新しいを初期化する必要がある場合List<T>、1つのアイデアは、匿名リストを作成し、それをクリアすることです。

var list = new[] { o, o1 }.ToList();
list.Clear();

//and you can keep adding.
while (....)
{
    ....
    list.Add(new { Id = x, Name = y });
    ....
}

または拡張メソッドとして、より簡単にする必要があります:

public static List<T> GetEmptyListOfThisType<T>(this T item)
{
    return new List<T>();
}

//so you can call:
var list = new { Id = 0, Name = "" }.GetEmptyListOfThisType();

またはおそらくさらに短く、

var list = new int[0].Select(x => new { Id = 0, Name = "" }).Tolist();

2

C#7以降を使用している場合は、匿名型の代わりにタプル型を使用できます。

var myList = new List<(int IntProp, string StrProp)>();
myList.Add((IntProp: 123, StrProp: "XYZ"));

1

この答えから、私はタスクを実行できる2つの方法を考え出しました。

    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't called, it is only used
    /// for the needed type inference. This overload is for when you don't have an instance of the anon class
    /// and don't want to make one to make the list.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(Func<T> definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }
    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't added to the list, it is
    /// only used for the needed type inference. This overload is for when you do have an instance of the anon
    /// class and don't want the compiler to waste time making a temp class to define the type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(T definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }

次のような方法を使用できます

var emptyList = CreateListOfAnonType(()=>new { Id = default(int), Name = default(string) });
//or
var existingAnonInstance = new { Id = 59, Name = "Joe" };
var otherEmptyList = CreateListOfAnonType(existingAnonInstance);

この回答にも同様の考え方がありますが、これらのメソッドを作成するまではわかりませんでした。


0

これで試してください:

var result = new List<object>();

foreach (var test in model.ToList()) {
   result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}

匿名型のリストはどこにありますか?
Micha Wiedenmann、

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.