2011-11-30 70 views
2

當我枚舉IEnumerable兩次Resharper抱怨Possible multiple enumerations of IEnumerable。我知道,在枚舉兩次的情況下,在DB查詢的某些情況下,您會遇到異常。如何創建無法枚舉多個枚舉的IEnumerable <T>?

我想在測試中重現該行爲。所以,我基本上要下面的函數拋出(因爲多個枚舉):

private void MultipleEnumerations(IEnumerable<string> enumerable) 
    { 
     MessageBox.Show(enumerable.Count().ToString()); 
     MessageBox.Show(enumerable.Count().ToString()); 
    } 

,我應該通過什麼呢?所有列表,集合等都可以使用多個枚舉。 即使這樣的IEnumerable的不給一個例外:

private IEnumerable<string> GetIEnumerable() 
    { 
     yield return "a"; 
     yield return "b"; 
    } 

感謝。

回答

3

你可能只是想自定義類:

public class OneShotEnumerable<T> : IEnumerable<T> 
{ 
    private readonly IEnumerable<T> _source; 
    private bool _shouldThrow = false; 

    public OneShotEnumerable(IEnumerable<T> source) 
    { 
     this._source = source; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     if (_shouldThrow) throw new InvalidOperationException(); 
     _shouldThrow = true; 

     return _source.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 
+0

謝謝,完美的作品:) – Shaddix

2

創建自己的類,實現IEnumerable<T>並拋出異常如果GetEnumerator()被調用兩次(使用布爾實例字段)。

或者,創建一個使用標誌字段的迭代器,以確保它不能被調用兩次(枚舉迭代器兩次將執行整個方法兩次)。

+0

的問題,在一個迭代使用標誌傳遞東西,你以前的方法是,國家將必須​​連接到類中的迭代器存在,而不是可枚舉本身。 –

+0

如果您想要一次性解決方案,標誌是一種好方法,謝謝。上課更好,國旗更快:) – Shaddix

+0

@JohnGietzen:我知道。這沒有什麼好方法。 – SLaks

1

自定義類,我已經從約翰Gietzen的答案複製(一對夫婦更正),可以有效地和一個擴展方法來創建相結合一個非常簡單的方法來做到這一點。

public class OneShotEnumerable<T> : IEnumerable<T> 
{ 
    private readonly IEnumerable<T> source; 
    private bool shouldThrow = false; 

    public OneShotEnumerable(IEnumerable<T> source) 
    { 
     this.source = source; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     if (shouldThrow) 
      throw new InvalidOperationException("This enumerable has already been enumerated."); 

     shouldThrow = true; 

     return this.source.GetEnumerator(); 
    } 
} 

public static clas OneShotEnumerableExtension 
{ 
    public static IEnumerable<T> SingleUse<T>(this IEnumerable<T> source) 
    { 
#if (DEBUG) 
     return new OneShotEnumerableExtension(source); 
#else 
     return source; 
#endif 
    } 
} 

然後,你可以通過簡單地做

MultipleEnumerations(MyEnumerable.SingleUse());