正确检查论点
在枚举返回值之前,不会执行迭代器方法。因此,在迭代器之外断言前置条件是有利的。
public static IEnumerable<int> Count(int start, int count)
{
// The exception will throw when the method is called, not when the result is iterated
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
return CountCore(start, count);
}
private static IEnumerable<int> CountCore(int start, int count)
{
// If the exception was thrown here it would be raised during the first MoveNext()
// call on the IEnumerator, potentially at a point in the code far away from where
// an incorrect value was passed.
for (int i = 0; i < count; i++)
{
yield return start + i;
}
}
呼叫侧码(用法):
// Get the count
var count = Count(1,10);
// Iterate the results
foreach(var x in count)
{
Console.WriteLine(x);
}
输出:
1
2
3
4
5
6
7
8
9
10
当方法使用 yield
生成可枚举时,编译器会创建一个状态机,当迭代时将运行代码到 yield
。然后它返回生成的项目,并保存其状态。
这意味着当你第一次调用方法(因为它创建状态机)时,你不会发现有关无效参数(传递 null
等),只有当你尝试访问第一个元素时(因为只有这样才能在方法由状态机运行)。通过将其包装在首先检查参数的常规方法中,你可以在调用方法时检查它们。这是快速失败的一个例子。
使用 C#7+时,CountCore
函数可以方便地作为局部函数隐藏在 Count
函数中。见这里的例子。