推荐的方法来检查一个序列是否为空
一个方法返回一个序列, IEnumerable<T>
,现在你想检查它是否为空。 你如何推荐这样做? 我正在寻找良好的可读性和良好的性能。
第一个也是最明显的方法是检查计数是否大于零:
if(sequence.Count() == 0)
有可观的可读性,但可怕的performance,因为它必须实际上贯穿整个序列。
我有时使用的方法如下:
if(!sequence.Any())
这不(据我所知)必须经历整个序列,但可读性有点落后和尴尬。 (如果我们检查序列不是空的,则读取更好)。
另一个select是在尝试捕获中使用First
,如下所示:
try { sequence.First(); } catch(InvalidOperationException) { // Do something }
不是一个非常漂亮的解决scheme,也可能更慢,因为它使用exception和东西。 当然可以通过使用FirstOrDefault
来防止,除非序列中的第一个项目实际上是默认值,否则会有很大的问题;)
那么,还有其他的方法来检查序列是否为空? 你通常使用哪一个? 你推荐使用哪一个?
注意:为了获得最佳的可读性,我可能会把上面的代码片段放到一个IsEmpty
扩展方法中,但是我还是很好奇,因为我也不得不在这个方法中做一些事情:p
我会使用!sequence.Any()
,亲自。
如果你真的需要,你可以随时写自己的扩展方法:
public static bool IsEmpty<T>(this IEnumerable<T> source) { return !source.Any(); }
那么你可以写:
if (sequence.IsEmpty())
您可以使用此实现创build一个扩展方法。
public static bool IsEmpty<T>(this IEnumerable<T> items) { using (var enumerator = items.GetEnumerator()) { return !enumerator.MoveNext(); } }
那么你调用的所有这些方法都是LINQ扩展方法,所以这取决于LINQ提供程序是如何实现的。 如果您想知道序列是否为空,则Count() == 0
或Any() == false
是适当的。 我更喜欢Any()
我自己。
但是,根据您的sequence
实际types,您可能不需要使用LINQ扩展方法。 也就是说,如果它是一个数组,你可以调用sequence.Length
。 如果它是一个集合,你可以使用sequence.Count
。
你说:
if(sequence.Count() == 0)
具有可观的可读性,但是由于它必须实际经历整个序列,所以性能很差。
这是真的吗? 你正在谈论处理一个接口 , IEnumerable<T>
,然而你正在做它的实现,可能会或可能不会是真实的假设。 实际上,这些年来我写的许多自定义集合都保留了一个私有variables,它在内部存储当前的计数,这意味着返回.Count
是一件微不足道的事情,不需要迭代整个集合。
所以说,除非你知道一个具体的实现是很差的.Count
优化,我会使用.Count
。 尽可能避免过早优化,并坚持可读性。
我使用这个扩展方法来检测序列是否为空或没有任何项目,或者检测序列是否至less有一个项目,就像string.IsNullOrEmpty()
方法一样。
public static bool IsNullOrEmpty<TSource>(this IEnumerable<TSource> source) { if (source == null) { return true; } return !source.Any(); } public static bool IsNotNullOrEmpty<TSource>(this IEnumerable<TSource> source) { return !source.IsNullOrEmpty(); } . . . if (!sequence.IsNullOrEmpty()) { //Do Something with the sequence... }