检查IEnumerable是否具有任何行而不枚举整个列表

Dav*_*New 14 .net c# linq ienumerable lazy-loading

我有以下方法返回一个IEnumerable类型T.该方法的实现并不重要,除了yield return延迟加载IEnumerable.这是必要的,因为结果可能有数百万项.

public IEnumerable<T> Parse()
{
    foreach(...)
    {
        yield return parsedObject;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:

我有以下属性可用于确定是否IEnumerable有任何项目:

public bool HasItems
{
    get
    {
        return Parse().Take(1).SingleOrDefault() != null;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做到这一点?

Mar*_*cus 34

IEnumerable.Any()将返回true如果有序列中的任何元素false,如果有序列中的元素.此方法不会迭代整个序列(只有最多一个元素),因为如果它超过第一个元素,它将返回true,否则返回false.

  • 这是不正确的.它确实开始迭代可枚举,但它不会迭代整个事物. (4认同)
  • 不,那是不对的.任何人都会做一个MoveNext但是不会修改集合,并且下面的foreach将从第一个项目开始(index = 0).这对你来说很容易测试! (4认同)
  • 请注意,这可能会导致一些意外的影响。例如,如果您首先检查enumerable.Any(),然后输入foreach来枚举您的可枚举,则由于Any()的工作方式,您将失去该枚举的第一个元素-它已经调用了e.MoveNext ()一次。 (3认同)
  • 但它不会迭代完整的序列,而只会迭代一项。 (2认同)
  • @davenewza这是一个linq方法.实施如下:http://pastebin.com/Acq7WL0E (2认同)
  • 下面的 foreach 将从第一项开始,但它将是一个新的枚举。这意味着您可能会收到意想不到的副作用:https://pastebin.com/y2AJvyKY (2认同)

drz*_*aus 7

类似于Howto: Count the items from a IEnumerable<T> without iterating? anEnumerable是一个懒惰的、向前阅读的“列表”,就像量子力学一样,研究它的行为会改变它的状态。

查看确认:https : //dotnetfiddle.net/GPMVXH

    var sideeffect = 0;
    var enumerable = Enumerable.Range(1, 10).Select(i => {
        // show how many times it happens
        sideeffect++;
        return i;
    });

    // will 'enumerate' one item!
    if(enumerable.Any()) Console.WriteLine("There are items in the list; sideeffect={0}", sideeffect);
Run Code Online (Sandbox Code Playgroud)

enumerable.Any()是检查列表中是否有任何项目的最干净的方法。您可以尝试转换为不懒惰的东西,例如if(null != (list = enumerable as ICollection<T>) && list.Any()) return true.

或者,您的方案可能允许Enumerator在枚举之前使用并进行初步检查:

var e = enumerable.GetEnumerator();
// check first
if(!e.MoveNext()) return;
// do some stuff, then enumerate the list
do {
    actOn(e.Current);  // do stuff with the current item
} while(e.MoveNext()); // stop when we don't have anything else
Run Code Online (Sandbox Code Playgroud)


小智 5

回答这个问题并消除所有疑虑的最佳方法是看看“Any”函数的作用。

   public static bool Any<TSource>(this IEnumerable<TSource> source) {
        if (source == null) throw Error.ArgumentNull("source");
        using (IEnumerator<TSource> e = source.GetEnumerator()) {
            if (e.MoveNext()) return true;
        }
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

https://github.com/microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs