3

一个新手问题。

C# 中的数组返回非泛型(经典)IEnumerator。其他收藏也可以提供。

一般来说,如果通用枚举器可用,是否更好,例如出于类型安全的原因?有时非通用选项更可取吗?

4

2 回答 2

2

通常最好使用泛型枚举,因为正如您在问题中提到的那样,类型安全。

如果您仅存储对象集合,则可以选择泛型枚举。因此,您无需编写IEnumerable<object>,而是编写IEnumerable并找出迭代中的真实对象类型(如果您需要,但通常是的)。

于 2012-06-27T10:24:58.740 回答
1

foreach实际上并不总是使用IEnumerable[<T>]/ IEnumerator[<T>]API 首先,它实际上不是必需的:只需要一个返回GetEnumerator()带有a的方法的方法,例如,具有自定义迭代器。这种方法在 .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 回答