我正在尝试找到最可重用但优雅的代码片段,以确定是否为IEnumerable。在理想情况下,这应该是一个函数,我可以在任何时候告诉我IEnumerable是否为空。
虽然我已经为.NET 3.5开发了一个迄今为止运行良好的答案,但我目前的想法是没有完美的答案,因为IEnumerable可以在技术上封装一个集合(或迭代器队列)来修改迭代时的基础结果,这会导致问题。但是,这也是实现IEnumerable.Count()的障碍,并没有阻止MS提供它。
所以我想我会把它放到SO上看看是否有人有更好的,以防万一其他人觉得它有用。
编辑:哇,我无法相信我不知道IEnumerable.Any。我知道它存在,但从来没有费心去检查它做了什么。让这成为一个教训。阅读文档。仅仅因为方法名称并不意味着它能够达到你想要的效果,并不意味着它不能达到你想要的效果。
答案 0 :(得分:22)
!enumerable.Any()
将尝试仅抓取第一个元素。
为了扩展它的工作方式/原因,任何确定IEnumerable
的任何组件是否与给定函数匹配,如果没有给出,那么任何组件都将成功,这意味着如果一个组件将返回true元素存在于可枚举中。
答案 1 :(得分:2)
对于.net 1/2:
IEnumerator e;
try
{
e = enumerable.GetEnumerator();
return e.MoveNext();
}
finally
{
if (e is IDisposable)
e.Dispose();
}
或者,使用泛型:
using (IEnumerator<T> e = enumerable.GetEnumerator())
{
return e.MoveNext();
}
答案 2 :(得分:2)
你说得对,没有完美的答案。 IEnumerable仅支持迭代,并不保证枚举是可重复的。您无法确定枚举是否包含元素而不调用MoveNext至少一次,并且一旦完成,您无法保证能够重用枚举:IEnumerable.Reset允许抛出NotSupportedException。来自http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx:
“为COM互操作性提供了Reset方法。它不一定需要实现;相反,实现者可以简单地抛出NotSupportedException。”
扩展方法,如IEnumerable&lt; T&gt; .Count和IEnumerable&lt; T&gt ;.Any需要调用MoveNext。有用的包装器,但不要避免在枚举不支持重置的(罕见)情况下,你可能会遇到问题。
答案 3 :(得分:0)
使用这些方法中的任何一个都要注意的是,并非所有枚举都可以回滚,例如System.Data.IDataReader的所有实现只能运行一次。
在这些情况下,您在foreach
循环中确实没有成本,只要您考虑到它甚至可能不会循环一次这一事实。
答案 4 :(得分:0)
第一种方法有一个简单的Empty扩展方法实现: http://signum.codeplex.com/SourceControl/changeset/view/25903#510468