IEnumerable是空的?
我知道这可能不重要/影响性能的大部分,但我讨厌获得IEnumerable
和做.Count()
的想法。 是否有一个IsEmpty
或NotEmpty
或某些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议并返回一个懒惰评估的枚举可能是合适的,只要消费者正在做一些不太耗时的事情(例如产生一些聚合值)。
在IEnumerable
或IEnumerable<T>
,不。
但它确实没有多大意义。 如果一个集合是空的,并且您尝试使用IEnumerable
对其进行迭代,则对IEnumerator.MoveNext()
的调用将简单地返回false,而不会降低性能。
我不这么认为, Count
就是这样。 此外,什么会更快:
- 访问属性并检索存储的
Integer
- 访问属性并检索存储的
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()将防止结束有空列表。
- 为什么Sun不把C#转换成Java字节码编译器?
- 将POP3客户端function集成到C#应用程序中?
- 在编译期间,“代码9009退出”是什么意思?
- 简单的喷油器vs Hiro vs Autofac
- Java vs C#:有没有比较执行速度的研究?
- 在C#中embeddedIronPython的问题(缺less编译器所需的成员“Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember”
- .NET数据结构:ArrayList,List,HashTable,Dictionary,SortedList,SortedDictionary – 速度,内存,以及何时使用?
- 我如何确定.NET应用程序的依赖关系?
- 如何使用WPF将文本包装到标签中?