正確檢查論點
在列舉返回值之前,不會執行迭代器方法。因此,在迭代器之外斷言前置條件是有利的。
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
函式中。見這裡的例子。