我有一个简单的对象数组:
Contact[] contacts = _contactService.GetAllContacts();
我想测试该方法是否返回any联系人。我真的很喜欢
Any()
的 LINQ 语法,因为它突出了我想要实现的目标:
if(!contacts.Any()) return;
但是,这比仅仅测试数组的长度慢吗?
if(contacts.Length == 0) return;
有什么方法可以让我知道
Any()
在这种情况下执行什么样的操作,而不必去这里询问?类似于 Profiler,但用于内存中的集合?
有两种
Any()
方法:
1. IEnumerable<T>
的扩展方法
2. IQueryable<T>
的扩展方法
我猜您正在使用
IEnumerable<T>
的扩展方法。那个看起来像这样:
public static bool Any<T>(this IEnumerable<T> enumerable)
{
foreach (var item in enumerable)
{
return true;
}
return false;
}
基本上,使用
Length == 0
更快,因为它不涉及为数组创建迭代器。
如果您想检查不属于您的代码(即已编译的代码),例如
Any<T>
,您可以使用某种反汇编程序。 Jetbrains 有一个免费的 - http://www.jetbrains.com/decompiler/
我必须完全不同意其他答案。 它当然不会迭代数组。它会稍微慢一些,因为它需要创建一个数组迭代器对象并调用
MoveNext()
once,但在大多数情况下该成本应该可以忽略不计;如果 Any()
使代码对您来说更具可读性,请随意使用它。
来源:反编译
Enumerable.Any<TSource>
代码。
如果您有一个数组,则长度位于数组的属性中。调用 Any 时,您将迭代数组以查找第一个元素。设置枚举器可能比仅读取 Length 属性更昂贵。
就你的情况而言
Length
是稍好一些:
// Just private field test if it's zero or not
if (contacts.Length == 0)
return;
// Linq overhead could be added: e.g. a for loop
// for (int i = 0; i < contains.Length; ++i)
// return true;
// plus inevitable private field test (i < contains.Length)
if (!contacts.Any())
return;
但差异似乎可以忽略不计。
在一般情况下,然而,
Any
更好,因为它停在找到的第一个项目上
// Itterates until 1st item is found
if (contains.Any(x => MyCondition(x)))
return;
// Itterates the entire collection
if (contains.Select(x => MyCondition(x)).Count() > 0)
return;
是的,它比较慢,因为它迭代元素。使用
Length
属性更好。但我仍然不认为存在显着差异,因为一旦找到项目,Any
就会返回true。
我刚刚运行了一个 BenchmarkDotNet 项目,该项目测量 100 元素 int 数组的
Any()
与 Length > 0
,结果是:
方法 | 意思是 | 错误 | 标准偏差 | 已分配 |
---|---|---|---|---|
任何 | 5.5362 纳秒 | 1.0495 纳秒 | 0.0575 纳秒 | - |
长度 | 0.2413纳秒 | 0.1316 纳秒 | 0.0072 纳秒 | - |
速度快了 30 倍。
附注实际上,如果您在 Visual Studio 中启用“代码分析器”,它实际上会告诉您“为了清晰起见和性能,更喜欢将‘长度’与 0 进行比较而不是使用‘Any()’@
P.P.S。我正在使用
.NET 8