2011-11-30 39 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());