【发布时间】:2019-02-18 13:44:04
【问题描述】:
所以我有两种方法都通过IEnumerable 集合执行迭代。
public static IEnumerable<int> GetRange(int start, int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
var end = start + count;
for (int value = start; value < end; value++)
{
yield return value;
}
}
public static IEnumerable<int> GetRangeFunction(int start, int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
var end = start + count;
return RangeEnumeration();
//Using local function
IEnumerable<int> RangeEnumeration()
{
for (var value = start; value < end; value++)
{
yield return value;
}
}
}
我最近知道返回 IEnumerable 的方法在枚举之前不会执行。
所以我创建了两个代码块来调用每个方法
调用 GetRange
var iterator = GetRange(0, 10); // This does not start the execution of `GetRange` method. Instead, it waits till any item is requested
foreach(var item in iterator) //Now the GetRange method is called
{
}
GetRangeFunction
但是,在 GetRangeFunction 的情况下,该方法在创建迭代器时立即被调用。
var iterator = GetRangeFunction(0, 5);
为什么会出现这种行为?我也在想GetRangeFunction,在请求项目之前不会执行。
编辑
我的问题表述得不好,让我再解释一遍。
两个枚举器都通过 yield 一个接一个地返回项目。但是在 GetRange 的情况下,在对枚举数进行任何操作之前,不会执行任何语句 (not even checking count is less than zero)。但是,在 GetRangeFunction 的情况下,条件检查会在调用该方法以创建迭代器时执行。
【问题讨论】:
-
will not be executed until enumerated- 它将执行到返回枚举器对象的位置。对于普通的迭代器函数,这将是直接,您可能认为它“没有执行”。 -
在编译期间是否只做出这些决定?如果我错了,请纠正我。
-
在迭代器循环之前和产量返回之前添加
Console.WriteLine。看看会发生什么。 -
@Steve,@GSerg 这实际上不是真的。使用
yield的整个方法只会在枚举时执行 -
@RudreshaParameshappa 请参阅The implementation of iterators in C# and its consequences (part 1)。编译器将 整个
IEnumerable<int> GetRange转换为状态机,因此在枚举之前不会执行其中的代码。但是IEnumerable<int> GetRangeFunction根本没有转换为状态机,只有IEnumerable<int> RangeEnumeration()是。
标签: c# .net .net-core ienumerable