匿名クラスの一般的なリスト
-
03-07-2019 - |
質問
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});
....
}
解決
できること:
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);
あなたはアイデアを得る:)
他のヒント
ここに答えがあります。
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);
これを行うには多くの方法がありますが、ここでの応答のいくつかは、不要な要素を含むリストを作成しているため、リストをクリアする必要があります。
ジェネリック型の空のリストを探している場合は、タプルのリストに対する選択を使用して空のリストを作成します。要素はインスタンス化されません。
空のリストを作成するためのワンライナーは次のとおりです。
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();
正確ではありませんが、List<object>
と言えばうまくいきます。ただし、list[0].Id
は機能しません。
これは、C#4.0のList<dynamic>
を使用することにより、実行時に 動作します。つまり、IntelliSenseは取得されません。
推測
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 });
}
通常は次のものを使用します。主に<!> quot; start <!> quot;空のリストで。
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" });
..これにより、最初の項目が既に追加された初期リストが表示されます。
コードでこれを行うことができます。
var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });
いくつかの回答でILをチェックしました。このコードは空のリストを効率的に提供します:
using System.Linq;
…
var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();
最新バージョン4.0では、以下のような動的を使用できます
var list = new List<dynamic>();
list.Add(new {
Name = "Damith"
});
foreach(var item in list){
Console.WriteLine(item.Name);
}
}
これが私の試みです。
List<object> list = new List<object> { new { Id = 10, Name = "Testing1" }, new {Id =2, Name ="Testing2" }};
カスタムタイプの匿名リストを作成するために似たようなものを書いたとき、私はこれを思いつきました。
匿名タイプのリストを作成する別の方法を次に示します。これにより、空のリストから開始できますが、IntelliSenseにアクセスできます。
var items = "".Select( t => new {Id = 1, Name = "foo"} ).ToList();
最初のアイテムを保持したい場合は、文字列に1文字入力するだけです。
var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();
これの代わりに:
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);
}
}
問題は、intellisenseがプロパティ id および name を表示するにもかかわらず、Objectのメンバーのみが実行時に利用できることです。
.net 4.0の解決策は、上記のコードで object の代わりにキーワード dynamic を使用することです。
別の解決策は、リフレクションを使用してプロパティを取得することです
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();
}
}
}
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);
動的リストを作成できます。
List<dynamic> anons=new List<dynamic>();
foreach (Model model in models)
{
var anon= new
{
Id = model.Id,
Name=model.Name
};
anons.Add(anon);
}
<!> quot; dynamic <!> quot;追加された最初の値によって初期化されます。
次の方法で実行できます。
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" });
少し<!> quot; hacky <!> quot;私には、しかしそれは機能します-あなたが本当にリストを持っている必要があり、匿名配列を使用できない場合。
これは古い質問ですが、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で説明されているように、魔法はタプルのカスタム拡張機能の追加メソッドに由来します。 。
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...
}
私が嫌いなのは、型が名前から分離されていることだけですが、本当に新しいクラスを作成したくない場合は、このアプローチでも読み取り可能なデータが得られます。
新しいList<T>
を初期化する必要がある2番目の例の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つの方法を思い付きました:
/// <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);
この回答にも同様の考えがありますが、これらのメソッドを作成するまでは表示されませんでした。
これを試してください:
var result = new List<object>();
foreach (var test in model.ToList()) {
result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}
static void Main()
{
List<int> list = new List<int>();
list.Add(2);
list.Add(3);
list.Add(5);
list.Add(7);
}