IEnumerable是空的?

我知道这可能不重要/影响性能的大部分,但我讨厌获得IEnumerable和做.Count()的想法。 是否有一个IsEmptyNotEmpty或某些function? (类似于stl empty())

您需要IEnumerable.Any()扩展方法(.Net Framework 3.5及更高版本)。 它避免了对元素的计数。

如果它不是通用的,就像这样

 enumeration.Cast<object>().Any(); 

如果它是通用的,就像已经说过的那样使用Enumerable的扩展

不需要任何LINQ,你可以做以下事情:

 bool IsEmpty(IEnumerable en) { foreach(var c in en) { return false; } return true; } 

请记住,IEnumerable只是一个接口。 它背后的实现可能会有很大的不同,从类到类(考虑乔的例子)。 扩展方法IEnumerable.Any()必须是一个通用的方法,可能不是你想要的(性能明智的)。 Yossarian提出了一个适用于许多类的方法,但是如果底层实现不使用“yield”,那么您仍然可以付出代价。

一般来说,如果你坚持包含在IEnumerable接口中的集合或数组,那么Cristobalito和Yossarian可能有最好的答案。 我的猜测是内置的.Any()ext方法是Yossarian推荐的。

您可以使用扩展方法,如Any()或Count()。 Count()比Any()更昂贵,因为它必须执行整个枚举,正如其他人指出的那样。

但是在懒惰评估(例如使用收益的方法)的情况下,要么是昂贵的。 例如,通过以下IEnumerable实现,每次调用Any或Count都会产生一个新的往返数据库的成本:

 IEnumerable<MyObject> GetMyObjects(...) { using(IDbConnection connection = ...) { using(IDataReader reader = ...) { while(reader.Read()) { yield return GetMyObjectFromReader(reader); } } } } 

我认为道德是:

  • 如果您只有一个IEnumerable<T> ,并且您想要做的不仅仅是枚举它(例如使用Count或Any),那么首先考虑将其转换为List(扩展方法ToList)。 这样你就保证只枚举一次。

  • 如果您正在devise一个返回集合的API,请考虑返回ICollection<T> (或甚至IList<T> ),而不是IEnumerable<T>因为很多人似乎都build议这样做。 通过这样做,你正在加强你的合同,以保证没有懒惰的评估(因此没有多重评估)。

请注意我在说你应该考虑返回一个集合,而不是总是返回一个集合。 从以下评论中可以看出,一如往常一样,是有取舍的。

  • @KeithS认为你永远不应该在DataReader上产生,虽然我永远不会说永远不会,但我认为一般来说,数据访问层应该返回一个ICollection<T>而不是惰性评估的IEnumerable<T> KeithS在他的评论中给出的理由。

  • @Bear Monkey指出,如果数据库返回大量的logging,在上面的例子中实例化一个List可能会很昂贵。 也是如此,在一些情况下(可能很less见),忽略@ KeithS的build议并返回一个懒惰评估的枚举可能是合适的,只要消费者正在做一些不太耗时的事情(例如产生一些聚合值)。

IEnumerableIEnumerable<T> ,不。

但它确实没有多大意义。 如果一个集合是空的,并且您尝试使用IEnumerable对其进行迭代,则对IEnumerator.MoveNext()的调用将简单地返回false,而不会降低性能。

我不这么认为, Count就是这样。 此外,什么会更快:

  1. 访问属性并检索存储的Integer
  2. 访问属性并检索存储的Boolean

您也可以编写自己的Count扩展方法重载,如下所示:

  /// <summary> /// Count is at least the minimum specified. /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="source"></param> /// <param name="min"></param> /// <returns></returns> public static bool Count<TSource>(this IEnumerable<TSource> source, int min) { if (source == null) { throw new ArgumentNullException("source"); } return source.Count(min, int.MaxValue); } /// <summary> /// Count is between the given min and max values /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="source"></param> /// <param name="min"></param> /// <param name="max"></param> /// <returns></returns> public static bool Count<TSource>(this IEnumerable<TSource> source, int min, int max) { if (source == null) { throw new ArgumentNullException("source"); } if (min <= 0) { throw new ArgumentOutOfRangeException("min", "min must be a non-zero positive number"); } if (max <= 0) { throw new ArgumentOutOfRangeException("max", "max must be a non-zero positive number"); } if (min >= max) throw new ArgumentOutOfRangeException("min and max", "min must be lest than max"); var isCollection = source as ICollection<TSource>; if (isCollection != null) return isCollection.Count >= min && isCollection.Count <= max; var count = 0; using (var enumerator = source.GetEnumerator()) { while (enumerator.MoveNext()) { count++; if (count >= min && count <= max) return true; } } return false; } 

使用Enumerable.Empty()而不是IEnumerable.Any()将防止结束有空列表。