.Any()
和.Length > 0
之间的区别,以及在测试集合是否有元素时为什么会使用它们中的任何一个。这让我有点困惑,因为这似乎有点显而易见,但感觉可能我漏掉了些什么。
我建议您在只需知道集合中是否有元素时使用
.Length
,而在希望过滤结果时使用.Any()
。很可能
.Any()
也会受到性能损失,因为它必须在内部进行循环/查询。.Any()
和.Length > 0
之间的区别,以及在测试集合是否有元素时为什么会使用它们中的任何一个。.Length
,而在希望过滤结果时使用.Any()
。.Any()
也会受到性能损失,因为它必须在内部进行循环/查询。Length
只存在于某些集合类型,如Array
。
Any
是可用于任何实现IEnumerable<T>
的集合的扩展方法。
如果有Length
属性,则可以使用它,否则使用Any
。
可能
.Any()
也会带来性能问题,因为它必须在内部执行循环/查询。
Enumerable.Any
不会进行循环。它获取一个迭代器并检查MoveNext
是否返回true。以下是来自.NET Reflector的源代码。
public static bool Any<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
return true;
}
}
return false;
}
IQueryable<T>
版本,但我不确定OP在谈论哪个,也许两个都是。编辑:通过集合,我猜你是对的,只是linq-to-entities。 - Nick CraverAny()
与Count() > 0
之间的区别(而不是Length > 0
)。基本上,情况如下:Any()
将枚举单个项来尝试确定集合是否有任何成员。(有一个重载方法使用Func<T, bool>
来检查给定条件,但我猜面试官指的是不带参数的Any()
版本。)这使得时间复杂度为O(1)。Count()
首先将检查T[]
或ICollection
或ICollection<T>
中的Length
或Count
属性。通常这会是O(1)。但是,如果不可用,它将通过枚举整个集合来计算项目数。这将是O(n)。Count
或Length
属性如果可用,与Any()
一样,很可能是O(1),并且可能表现更好,因为根本不需要枚举。但是Count()
扩展方法不能保证这一点。因此,有时是O(1),有时是O(n)。假设你正在处理一个不明确实现ICollection<T>
的IEnumerable<T>
,并且你不知道它是否实现了, 如果你的意图仅是确保集合不为空,则使用Any()
比Count() > 0
要好得多。.Length... System.Array.Any... IEnumerable(扩展方法)。
我更喜欢在可以找到它的情况下使用“length”。属性比任何方法调用都要轻量级。
尽管如此,“Any”的实现不会做更多的事情,只会执行下面提到的代码。
private static bool Any<T>(this IEnumerable<T> items)
{
return items!=null && items.GetEnumerator().MoveNext();
}
Length
是数组类型的属性,而Any()
是Enumerable
的扩展方法。因此,在处理数组时只能使用Length。在处理更抽象的类型(例如 IEnumerable<T>
)时,可以使用Any()。
我认为这是一个更普遍的问题,当我们有两种表达方式时该选择哪一种。 在这种情况下,我建议引用Peter Norvig在他的书PAIP中的话:“具体化”
具体化意味着使用最能描述你正在做的事情的方法。 因此,你想要表达的是:
collection.isEmpty()
.Length > 0
不是最好的选择,因为它强制规定您可以对对象进行大小调整。
假设您实现了无限列表。.Lenght
显然不起作用。int[] foo = new int[10];
这里 foo.Length 是 10。虽然这是正确的,但可能不是您要寻找的答案,因为我们尚未向数组添加任何内容。如果 foo 为空,它将抛出异常。
这听起来很像 Stackoverflow 上的一个问题,关于使用 .Count 和 .Any 来检查结果是否存在的区别:在 Linq-to-xml 中检查结果是否存在
在这种情况下,最好使用 Any 而不是 Count,因为 Count 会迭代 IEnumerable 的所有元素。
.Count()
会 使用ICollection
(通用或非通用)上的.Count
(例如在Array上获取.Length
)属性,而.Any()
则不使用,它将进行枚举,您可以启动Reflector来查看此信息,在 .Net 4中仍然如此。在IEnumerable<T>
上,IQueryable<T>
是另一回事。 - Nick CraverAny()
(至少重载不带参数的)将枚举一个项目。如果基础的 IEnumerable<T>
不是 ICollection<T>
,则 Count()
将枚举所有项目。因此,如果集合类型未知,则使用 Any()
比 Count() > 0
更有意义。 - Dan TaoICollection <T>
的Count
属性的成本也是未知的。总会有未知因素;对于未知类型的IEnumerable <T>
,对我来说,Any()
似乎是更好的教育猜测。 - Dan Tao关于讨论的目的。所有源代码都可用,因此您知道: 如果您正在使用具有Length或Count属性的实例,则始终具有O(1)。该值是您实例的成员,您可以直接与任何其他值进行比较。它只是两个值之间的比较操作。
扩展方法Any()总是首先创建一个新的迭代器,然后尝试获取第一个元素。它也是O(1),但由于每次调用Any()时都会分配一小部分内存用于此迭代器,因此会创建一个新的迭代器。在MoveNext()的内部实现中,该迭代器使用了2个比较操作和一个基于索引的访问列表,因为MoveNext还将当前值保存为成员以进行迭代(请参见List的枚举器的实现) 这就是为什么如果可以使用,则应优先使用Count或Length属性。
.Length
迭代集合并返回元素数量。复杂度为 O(n)
.Any
检查集合是否至少有一个项目。复杂度为 O(1)
。
.Count()
是一个选项吗?如果可用,它将使用.Length
(实际上是从ICollection
接口的.Count
);如果不可用,则枚举……像这样的.Any()
没有快捷方式。 - Nick Craver.length
和集合的.count
,则它们会被预先计算。因此,我只会在它们不可用或者我想要进行条件.any(lambda)
检查时使用.any()
。 - Nope