一个新手问题。
C# 中的数组返回非泛型(经典)IEnumerator。其他收藏也可以提供。
一般来说,如果通用枚举器可用,是否更好,例如出于类型安全的原因?有时非通用选项更可取吗?
一个新手问题。
C# 中的数组返回非泛型(经典)IEnumerator。其他收藏也可以提供。
一般来说,如果通用枚举器可用,是否更好,例如出于类型安全的原因?有时非通用选项更可取吗?
通常最好使用泛型枚举,因为正如您在问题中提到的那样,类型安全。
如果您仅存储对象集合,则可以选择非泛型枚举。因此,您无需编写IEnumerable<object>
,而是编写IEnumerable
并找出迭代中的真实对象类型(如果您需要,但通常是的)。
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
循环。