正確檢查論點

在列舉返回值之前,不會執行迭代器方法。因此,在迭代器之外斷言前置條件是有利的。

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

.NET 小提琴現場演示

當方法使用 yield 生成可列舉時,編譯器會建立一個狀態機,當迭代時將執行程式碼到 yield。然後它返回生成的專案,並儲存其狀態。

這意味著當你第一次呼叫方法(因為它建立狀態機)時,你不會發現有關無效引數(傳遞 null 等),只有當你嘗試訪問第一個元素時(因為只有這樣才能在方法由狀態機執行)。通過將其包裝在首先檢查引數的常規方法中,你可以在呼叫方法時檢查它們。這是快速失敗的一個例子。

使用 C#7+時,CountCore 函式可以方便地作為區域性函式隱藏在 Count 函式中。見這裡的例子。