2011-05-26 95 views
2

我正在開發一個集合類,它應該實現IEnumerator和IEnumerable。實現集合的簡單方法?

在我的第一種方法中,我直接實現了它們。現在我已經發現了yield關鍵字,並且我已經能夠簡化一切,用readonly屬性代替IEnumerator/IEnumerable接口。使用yield的值在循環中返回IEnumerable。

我的問題:是否有可能使用yield,這樣我就可以迭代類本身,而不實現IEnumerable/IEnumerator?

即,我希望有類似框架的集合一個功能:

List<int> myList = new List<int>(); 
foreach (int i in myList) 
{ 
    ... 
} 

這是可能的呢?

更新:看來我的問題措辭不妙。我不介意實現IEnumerator或IEnumerable;我只是認爲唯一的方法就是使用舊的Current/MoveNext/Reset方法。

+0

我想不出任何理由,這將是一個好主意。我缺乏想象力嗎? IEnumerator不是一個複雜或繁瑣的界面。 – Jodrell 2011-05-26 09:05:12

+0

@Jodrell:讓事情變得更簡單並不是一個好主意?爲什麼? – raven 2011-05-26 09:23:51

+0

爲什麼你的收藏應該實現'IEnumerator '? – CodesInChaos 2011-05-26 09:23:55

回答

8

你不會實施IEnumerable<T>IEnumerable得到foreach工作 - 但它會是一個好主意,這樣做。這是很容易做到:

public class Foo : IEnumerable<Bar> 
{ 
    public IEnumerator<Bar> GetEnumerator() 
    { 
     // Use yield return here, or 
     // just return Values.GetEnumerator() 
    } 

    // Explicit interface implementation for non-generic 
    // interface; delegates to generic implementation. 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

實現IEnumerable<T>只想打電話給你Values財產,但仍然提供了一個GetEnumerator()方法的選擇:

public class Foo 
{ 
    public IEnumerator<Bar> GetEnumerator() 
    { 
     // Use yield return here, or 
     // just return Values.GetEnumerator() 
    } 
] 

雖然這工作,它意味着您將無法將您的收藏集傳遞給期望IEnumerable<T>的任何內容,例如LINQ to Objects。

這是一個鮮爲人知的事實是foreach將與任何類型的支持GetEnumerator()方法,它返回適當MoveNext()Current成員類型的工作。這實際上是允許泛型之前的強類型集合,在集合上迭代不會包含值類型等。現在真的沒有要求它,IMO。

+0

感謝您提供快速和完整的答案。出於某種原因,我認爲yield只能用於返回IEnumerable。 – raven 2011-05-26 09:26:48

+0

@Jaime:如果你去http://manning.com/skeet,你仍然可以免費獲得C#深度第一版的第6章。這一章是關於迭代器塊:) – 2011-05-26 09:35:49

+0

@Jon Skeet,第8章看起來不錯。 – Jodrell 2011-05-26 09:42:12

1

你可以做這樣的事情,但爲什麼? IEnumerator已經很簡單了。

Interface MyEnumerator<T> 
{ 
    public T GetNext(); 
} 

public static class MyEnumeratorExtender 
{ 
    public static void MyForeach<T>(this MyEnumerator<T> enumerator, 
     Action<T> action) 
    { 
     T item = enumerator.GetNext(); 
     while (item != null) 
     { 
      action.Invoke(item); 
      item = enumerator.GetNext(); 
     } 
    } 
} 

我寧願有in關鍵字,我不想重寫linq。

+0

對不起,誤會。如上所述,我認爲用yield來實現IEnumerator是不可能的,但現在我知道更好了,我不介意這樣做:-) – raven 2011-05-26 11:54:51

相關問題