3

初心者の質問です。

C# の配列は、非ジェネリック (クラシック) IEnumerator を返します。他のコレクションはいずれかを提供できます。

一般に、たとえば型安全性の理由から、ジェネリック列挙子が利用可能な場合はそれを使用する方がよいでしょうか? 非汎用オプションが望ましい場合はありますか?

4

2 に答える 2

2

通常、質問で述べたように、型の安全性のために、ジェネリック列挙を使用することを強くお勧めします。

オブジェクトのコレクションだけを格納する場合は、非ジェネリック列挙を選択できます。したがって、 を記述する代わりに、反復内で実際のオブジェクト型IEnumerable<object>を記述IEnumerableして把握します (必要な場合は、通常は必要です)。

于 2012-06-27T10:24:58.740 に答える
1

foreachIEnumerable[<T>]/ IEnumerator[<T>]API実際に常に使用しているわけではありません。まず、実際には必須ではありません。必要なのは、 andを使用して何かGetEnumerator()返すメソッドだけです。たとえば、カスタム イテレータがあります。このアプローチは、.NET 1.1 でも一般的で、カスタム イテレータを優先することでボックス化を回避しました。bool MoveNext()Current {get;}List<T>

ただし、配列の場合は、さらに興味深いことがあります。検討:

    static void Main()
    {
        foreach(var i in GetData()) Console.WriteLine(i);
    }
    static int[] GetData()
    {
        int[] data = { 1, 2, 3, 4, 5 };
        return data;
    }

ここで、Mainにコンパイルされます(//コメントは私のものです):

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] int32[] CS$6$0000,
        [2] int32 CS$7$0001)

    // int[] arr = GetData()
    L_0000: call int32[] ConsoleApplication7.Program::GetData()
    L_0005: stloc.1

    // int j = 0
    L_0006: ldc.i4.0 
    L_0007: stloc.2

    // run end-condition of for loop first...
    L_0008: br.s L_0018

    // i = arr[j]
    L_000a: ldloc.1 
    L_000b: ldloc.2 
    L_000c: ldelem.i4          
    L_000d: stloc.0

    // Console.WriteLine(i);
    L_000e: ldloc.0 
    L_000f: call void [mscorlib]System.Console::WriteLine(int32)

    // j++
    L_0014: ldloc.2 
    L_0015: ldc.i4.1 
    L_0016: add 
    L_0017: stloc.2

    // j < arr.Length
    L_0018: ldloc.2 
    L_0019: ldloc.1 
    L_001a: ldlen 
    L_001b: conv.i4
    L_001c: blt.s L_000a

    L_001e: ret 
}

これは、列挙子 APIをまったく使用しません。実際にはforループとして実装されています。

于 2012-06-27T10:33:02.457 に答える