Chapter 4 - Item 33 : Generate Sequence Items as Requested

Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得

yield return 只有在元素被訪問時才運行,除了不需事前儲存集合也能透過篩選條件只取用必要元素。利用 ToList 方法也確保回傳集合是新的物件,在設計的需求上可以避免物件重覆參考的情況。

範例:

public static IList<int> createSequence( int numberOfElements,
    int startAt, int stepBy )
{
    var collection = new List<int>( numberOfElements );

    for ( var i = 0; i < numberOfElements; i++ )
        collection.Add( startAt + i * stepBy );

    return collection;
}

var data = new BindingList<int>( createSequence( 100, 0, 5 ) );

BindingList 內類別成員儲存的是 IList 物件參考而非建立集合副本,若程式內有其他地方擁有該物件參考,會造成 BindingList 內物件集合被修改的未預期結果。createSequence 內建立了 List<int> 物件並回傳,意味著該方法完整的將所有結果回傳,沒有機會讓外部依照條件選擇並產生對應的結果;可能造成多餘的資源浪費。 

接著利用 yield return 改寫範例。

public static IEnumerable<int> createSequenceV2( int numberOfElements,
    int startAt, int stepBy )
{
    for ( var i = 0; i < numberOfElements; i++ )
        yield return startAt + i * stepBy;
}

var data2 = new BindingList<int>( createSequenceV2( 100, 0, 5 ).ToList( ) );

ToList 回傳的是新的集合副本而非物件參考,避免重覆參考的問題。

var sequence = createSequenceV2( 100000, 0, 7 ).
    TakeWhile( num => num < 1000 );

利用 TakeWhile 方法,外部可依照條件決定回傳的結果,避免資源浪費。

結論:
1. 利用 yield return 回傳必要的結果。

2. 利用 yield return 回傳的結果呼叫 ToList,確保物件間不會重覆參考。