9

メソッドによって返されたときに一度だけ使用するために、いくつかのプロパティを保持する単純なクラスまたは構造体を宣言する回数。ありがたいことに、実行時にその場で宣言できる匿名オブジェクトが常にあると思うことが多すぎます。

その考えを念頭に置いて、そのような匿名オブジェクトの 1 つの配列を宣言する方法を知りたいと思います。

例:

var Employee = new { ID = 5, Name= "Prashant" };

これにより、整数と文字列の 2 つのプロパティを持つ匿名オブジェクトが作成されました。

ここではすべて問題ありませんが、この種のオブジェクトの配列をどのように宣言すればよいでしょうか。また、aforforeachループの両方を使用して配列を反復することをどのように推奨しますか。

foreach ループは宣言された型を想定しているため、foreachループは本当に問題だと思います。それでもアウェイがあるかもしれませんが、もしあればもちろんそれも知りたいです。

4

4 に答える 4

21

メソッドによって返されたときに一度だけ使用するために、いくつかのプロパティを保持する単純なクラスまたは構造体を宣言する回数。ありがたいことに、実行時にその場で宣言できる匿名オブジェクトが常にあると思うことが多すぎます。

1 番目と 2 番目の文は、矛盾した目的を念頭に置いていることを示しています。戻り値の型を宣言する方法がないため、匿名型、つまり匿名型の配列をメソッドから簡単に返すことはできません。一時的なローカル変数には匿名型のみを使用するようにしてください。

その考えを念頭に置いて、そのような匿名オブジェクトの 1 つの配列を宣言する方法を知りたいと思います。

このような:

var array = new[] 
  { 
    new { X = 123, Y = 456 }, 
    new { X = 345, Y = 567 } 
  };

for ループと foreach ループの両方を使用して反復することをどのように推奨しますか。

foreach(var item in array) 
...

また

for (int i = 0; i < array.Length; i += 1)
{
    var item = array[i];
    ...
}
于 2013-01-02T01:01:09.183 に答える
5

[編集 - 人口、基本的な列挙などを表示するように更新]

@Eveが言うように、LINQはあなたの友達です。一般的な経験則として、匿名型を渡そうとしないでください -あなたが賢明であれば可能です- しかし、それらが宣言されたコンテキスト/スコープの外でそれらを処理するのは大変な苦痛です.

要するに、楽しい思考実験として「匿名型の配列を宣言する」方法を見てみることにし、次のように思いつきました。

(注:「ダンプ」は、これがLINQPadに書き込まれているためです)

// Our anonymous type sequence
var anonymousEnumerable = Enumerable
        .Range(0, 10)
        .Select(i => new { ID = i, Text = i.ToString() });
var enumerableCount = anonymousEnumerable.Count();
var anonymousType = anonymousEnumerable.First().GetType();

// Option #1 - declare it as dynamic, i.e., anything goes
dynamic[] asDynamicArray = new dynamic[enumerableCount];
foreach(var tuple in anonymousEnumerable.Select((item, i) => Tuple.Create(i, item)))
{
    asDynamicArray[tuple.Item1] = tuple.Item2;
}

// Let's go the IEnumerable route
foreach (var asDynamic in asDynamicArray)
{
    Console.WriteLine("ID:{0} Text:{1}", asDynamic.ID, asDynamic.Text);
}

// Lowest common denominator: *everything* is an object
object[] asObjectArray = new object[enumerableCount];
foreach(var tuple in anonymousEnumerable.Select((item, i) => Tuple.Create(i, item)))
{
    asObjectArray[tuple.Item1] = tuple.Item2;
}

// Let's iterate with a for loop - BUT, it's now "untyped", so things get nasty
var idGetterMethod = anonymousType.GetMethod("get_ID");
var textGetterMethod = anonymousType.GetMethod("get_Text");
for(int i=0;i < asObjectArray.Length; i++)
{
    var asObject = asObjectArray[i];
    var id = (int)idGetterMethod.Invoke(asObject, null);
    var text = (string)textGetterMethod.Invoke(asObject, null);
    Console.WriteLine("ID:{0} Text:{1}", id, text);
}

// This is cheating :)
var letTheCompilerDecide = anonymousEnumerable.ToArray();
foreach (var item in letTheCompilerDecide)
{
    Console.WriteLine("ID:{0} Text:{1}", item.ID, item.Text);
}

// Use reflection to "make" an array of the anonymous type
var anonymousArrayType = anonymousType.MakeArrayType();
var reflectIt = Activator.CreateInstance(
          anonymousArrayType, 
          enumerableCount) as Array;    
Array.Copy(anonymousEnumerable.ToArray(), reflectIt, enumerableCount);  

// We're kind of in the same boat as the object array here, since we
// don't really know what the underlying item type is
for(int i=0;i < reflectIt.Length; i++)
{
    var asObject = reflectIt.GetValue(i);
    var id = (int)idGetterMethod.Invoke(asObject, null);
    var text = (string)textGetterMethod.Invoke(asObject, null);
    Console.WriteLine("ID:{0} Text:{1}", id, text);
}
于 2013-01-02T01:01:01.810 に答える
0

LINQ を使用して、必要なものを実現できます。これが例です。

int[] ids = {10, 15, 99};
string[] names = {"John", "Phil", "Jack"};
var array = ids.Zip(names, (id, name) => new {ID = id, Name = name}).
                ToArray();

または、配列だけが必要でデータがない場合は、この回避策を使用できます。ただし、結果はArray要素のタイプに関する情報を持たない になります。

var sample = new {ID = default(int), Name = default(string)};
var arrayLength = 10;
var array = Array.CreateInstance(sample.GetType(), arrayLength);

繰り返しについては、 /ループで使用varして、型を宣言する問題を回避できます。forforeach

foreach (var item in array)
{
    //Do something
}

for (var i = 0; i < array.Length; i++)
{
    var item = array[i];
    //Do something
}

編集:サンプルに基づいて、任意の数の要素を持つ空の配列を作成する別の回避策。

public static T[] GetArray<T>(T sample, int amount)
{
    return new T[amount];
}
于 2013-01-02T00:49:04.227 に答える
0

varで使用できますforeach:

var Employee1 = new { ID = 5, Name = "Prashant" };
var Employee2 = new { ID = 1, Name = "Tim" };
var employees = new[] { Employee1, Employee2 };

foreach (var employee in employees)
{
    Console.WriteLine("ID:{0}, Name:{1}", employee.ID, employee.Name);
}

for (int i = 0; i < employees.Length; i++)
{
    Console.WriteLine("ID:{0}, Name:{1}", employees[i].ID, employees[i].Name);
}

デモ

于 2013-01-02T00:59:21.363 に答える