標籤:
建議24:迭代器應該是唯讀
如果注意觀察會發現,FCL中的迭代器只有GetEnumerator方法,沒有SetEnumerator方法,所有的集合類也沒有一個可以寫的迭代器屬性。原因有二:
一:這違背了設計模式的開閉原則。被設定到集合中的迭代器可能會直接導致集合的行為發生異常或變動。一旦確實需要新的迭代要求,完全可以建立一個新的迭代器來滿足需求,而不是為集合設定該迭代器,因為這樣做會直接導致使用該集合對象的其他迭代情境發生不可知的行為。
二:現在,我們有了LINQ。使用LINQ可以不用建立任何新的類型就能滿足任何的迭代需求。
如果迭代器可寫,危害樣本如下:
假設存在一個公用集合對象,有兩個業務類需要對這個集合進行操作。
業務類A只負責將元素迭代顯示到UI上:
private IMyEnumerable list = new MyList(); private IMyEnumerator enumerator = list.GetEnumerator(); while(enumerator.MoveNext()) { int current = enumerator.Current; Console.WriteLine(current.ToString()); }
業務類B出於自己的某種需求,要實現一個新的針對集合對象的迭代器:
private MyEnumerator2 enumerator2 = new MyEnumerator2(list as MyList); (list as MyList).SetEnumerator(enumerator2); while(enumerator2.MoveNext()) { int current = enumerator2.Current; Console.WriteLine(current.ToString()); }
現在再回到業務類A執行一次迭代,結果將會是B所設定的迭代器輸出。這相當於B在沒有通知A的情況下進行了幹擾,這是應該避免的。
事實上,上面的代碼即使沒有下面這行代碼也會啟動並執行很好:
(list as MyList).SetEnumerator(enumerator2);
所以,不要為迭代器設定可寫屬性。
轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技
編寫高品質代碼改善C#程式的157個建議——建議24:迭代器應該是唯讀