Mat*_*ton 122 .net c# linq list
什么是"最佳"(考虑到速度和可读性)的方式来确定列表是否为空?即使列表是类型IEnumerable<T>且没有Count属性.
现在我在这之间折腾:
if (myList.Count() == 0) { ... }
Run Code Online (Sandbox Code Playgroud)
还有这个:
if (!myList.Any()) { ... }
Run Code Online (Sandbox Code Playgroud)
我的猜测是第二个选项更快,因为它会在看到第一个项目后立即返回结果,而第二个选项(对于IEnumerable)将需要访问每个项目以返回计数.
话虽如此,第二个选项看起来是否可读?你更喜欢哪个?或者你能想出一个更好的方法来测试空列表吗?
编辑 @ lassevk的响应似乎是最合乎逻辑的,再加上一些运行时检查,如果可能的话,使用缓存计数,如下所示:
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list is ICollection<T>) return ((ICollection<T>)list).Count == 0;
return !list.Any();
}
Run Code Online (Sandbox Code Playgroud)
ang*_*son 100
你可以这样做:
public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
if (source == null)
return true; // or throw an exception
return !source.Any();
}
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,如果底层源实际上具有快速Count属性,那么简单地使用.Count方法将会很快.上面的有效优化是检测一些基类型并简单地使用它们的.Count属性,而不是.Any()方法,但如果不能保证,则回退到.Any().
Dan*_*Tao 14
我会对你似乎已经确定的代码做一个小的补充:同时检查ICollection,因为这甚至是由一些非过时的泛型类(即,Queue<T>和Stack<T>)实现的.我也会使用as而不是is因为它更惯用,并且已被证明更快.
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list == null)
{
throw new ArgumentNullException("list");
}
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
return genericCollection.Count == 0;
}
var nonGenericCollection = list as ICollection;
if (nonGenericCollection != null)
{
return nonGenericCollection.Count == 0;
}
return !list.Any();
}
Run Code Online (Sandbox Code Playgroud)
LINQ本身必须以某种方式围绕Count()方法进行一些严格的优化.
这让你感到惊讶吗?我想,对于IList实现,Count只需直接读取元素的数量,同时Any必须查询IEnumerable.GetEnumerator方法,创建实例并MoveNext至少调用一次.
/编辑@Matt:
我只能假设IEnumerable的Count()扩展方法是这样的:
是的,当然可以.这就是我的意思.实际上,它使用ICollection而不是IList结果是相同的.
我刚写了一个快速测试,试试这个:
IEnumerable<Object> myList = new List<Object>();
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();
Run Code Online (Sandbox Code Playgroud)
第二个差不多慢三倍:)
再次使用堆栈或数组或其他场景尝试秒表测试,它实际上取决于它看起来的列表类型 - 因为它们证明Count更慢.
所以我想这取决于你正在使用的列表类型!
(只是要指出,我在列表中放置了2000多个对象,计数仍然更快,与其他类型相反)
List.Count根据微软的文档是 O(1):http :
//msdn.microsoft.com/en-us/library/27b47ht3.aspx
所以只是使用List.Count == 0它比查询快得多
这是因为它有一个名为 Count 的数据成员,它会在任何时候从列表中添加或删除某些内容时更新,因此当您调用List.Count它时,不必遍历每个元素来获取它,它只返回数据成员。