【问题标题】:c# generic versus non generic enumeratorsc# 泛型与非泛型枚举器
【发布时间】:2012-06-28 18:09:06
【问题描述】:

一个新手问题。

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

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

【问题讨论】:

  • 请记住,数组在 C# 1 中,而泛型直到 C# 2 才出现,因此数组(以及 ArrayListHashTable 等)返回它们会很棘手......

标签: c# generics enumerable


【解决方案1】:

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

非泛型枚举可以在您仅存储对象集合的情况下成为一种选择。 因此,您无需编写IEnumerable<object>,而是编写IEnumerable 并找出迭代中的real 对象类型(如果需要,但通常是的)。

【讨论】:

    【解决方案2】:

    foreach 实际上并不总是使用IEnumerable[<T>] / IEnumerator[<T>] API 。首先,它实际上不是必需的:所有必需 是一个GetEnumerator() 方法,它返回带有bool MoveNext()Current {get;}something - 例如,@ 987654327@ 有一个自定义迭代器。这种方法在 .NET 1.1 中也很常见,通过优先使用自定义迭代器来避免装箱。

    然而,在数组的情况下,它可能更有趣;考虑:

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

    这里,Main 编译为(// cmets 是我的):

    .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 循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多