当前位置:  开发笔记 > 编程语言 > 正文

使用LINQ检查列表是否为空

如何解决《使用LINQ检查列表是否为空》经验,为你挑选了4个好方法。

什么是"最佳"(考虑到速度和可读性)的方式来确定列表是否为空?即使列表是类型IEnumerable且没有Count属性.

现在我在这之间折腾:

if (myList.Count() == 0) { ... }

还有这个:

if (!myList.Any()) { ... }

我的猜测是第二个选项更快,因为它会在看到第一个项目后立即返回结果,而第二个选项(对于IEnumerable)将需要访问每个项目以返回计数.

话虽如此,第二个选项看起来是否可读?你更喜欢哪个?或者你能想出一个更好的方法来测试空列表吗?

编辑 @ lassevk的响应似乎是最合乎逻辑的,再加上一些运行时检查,如果可能的话,使用缓存计数,如下所示:

public static bool IsEmpty(this IEnumerable list)
{
    if (list is ICollection) return ((ICollection)list).Count == 0;

    return !list.Any();
}

angry person.. 100

你可以这样做:

public static Boolean IsEmpty(this IEnumerable source)
{
    if (source == null)
        return true; // or throw an exception
    return !source.Any();
}

编辑:请注意,如果底层源实际上具有快速Count属性,那么简单地使用.Count方法将会很快.上面的有效优化是检测一些基类型并简单地使用它们的.Count属性,而不是.Any()方法,但如果不能保证,则回退到.Any().



1> angry person..:

你可以这样做:

public static Boolean IsEmpty(this IEnumerable source)
{
    if (source == null)
        return true; // or throw an exception
    return !source.Any();
}

编辑:请注意,如果底层源实际上具有快速Count属性,那么简单地使用.Count方法将会很快.上面的有效优化是检测一些基类型并简单地使用它们的.Count属性,而不是.Any()方法,但如果不能保证,则回退到.Any().


或者使用一行并返回(source == null)?true:!source.Any(); (如果你没有抛出异常)

2> Dan Tao..:

我会对你似乎已经确定的代码做一个小的补充:同时检查ICollection,因为这甚至是由一些非过时的泛型类(即,QueueStack)实现的.我也会使用as而不是is因为它更惯用,并且已被证明更快.

public static bool IsEmpty(this IEnumerable list)
{
    if (list == null)
    {
        throw new ArgumentNullException("list");
    }

    var genericCollection = list as ICollection;
    if (genericCollection != null)
    {
        return genericCollection.Count == 0;
    }

    var nonGenericCollection = list as ICollection;
    if (nonGenericCollection != null)
    {
        return nonGenericCollection.Count == 0;
    }

    return !list.Any();
}



3> Konrad Rudol..:

LINQ本身必须以某种方式围绕Count()方法进行一些严格的优化.

这让你感到惊讶吗?我想,对于IList实现,Count只需直接读取元素的数量,同时Any必须查询IEnumerable.GetEnumerator方法,创建实例并MoveNext至少调用一次.

/编辑@Matt:

我只能假设IEnumerable的Count()扩展方法是这样的:

是的,当然可以.这就是我的意思.实际上,它使用ICollection而不是IList结果是相同的.



4> crucible..:

我刚写了一个快速测试,试试这个:

 IEnumerable myList = new List();

 Stopwatch watch = new Stopwatch();

 int x;

 watch.Start();
 for (var i = 0; i <= 1000000; i++)
 {
    if (myList.Count() == 0) x = i; 
 }
 watch.Stop();

 Stopwatch watch2 = new Stopwatch();

 watch2.Start();
 for (var i = 0; i <= 1000000; i++)
 {
     if (!myList.Any()) x = i;
 }
 watch2.Stop();

 Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
 Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
 Console.ReadLine();


第二个差不多慢三倍:)

再次使用堆栈或数组或其他场景尝试秒表测试,它实际上取决于它看起来的列表类型 - 因为它们证明Count更慢.

所以我想这取决于你正在使用的列表类型!

(只是要指出,我在列表中放置了2000多个对象,计数仍然更快,与其他类型相反)


`Enumerable.Count ()`对`ICollection `有特殊处理.如果您尝试使用*基本列表以外的其他*,我希望您会看到*显着*不同(较慢)的结果.但是,任何()`都将保持不变.
我必须同意马克; 这不是一个真正公平的考验.
推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有