9

我正在尝试找到最可重用但最优雅的代码段,用于确定是否为 IEnumerable。理想情况下,这应该是一个我可以在需要判断 IEnumerable 是否为空时绝对调用的函数。

虽然我已经为 .NET 3.5 开发了一个到目前为止对我来说效果很好的答案,但我目前的想法是没有完美的答案,因为 IEnumerable 可以在技术上封装一个集合(或迭代器队列),将底层结果修改为它会迭代,这会导致问题。但是,这也会成为实现 IEnumerable.Count() 的障碍,但这并没有阻止 MS 提供它。

所以我想我会把它交给 SO 看看是否有人有更好的,以防其他人发现它有用。

编辑: 哇,我不敢相信我不知道 IEnumerable.Any。我知道它存在,但从来没有费心去检查它做了什么。让这成为一个教训。阅读文档。仅仅因为方法名称并不意味着它会做你想做的事,并不意味着它不会做你想做的事。

4

5 回答 5

22
!enumerable.Any()

将尝试仅抓取第一个元素。

为了扩展其工作方式/原因,any 确定是否有任何组件IEnumerable与给定函数匹配,如果没有给出,则任何组件都将成功,这意味着如果元素存在于可枚举中,该函数将返回 true。

于 2008-09-22T20:22:44.797 回答
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();
}
于 2008-09-22T20:39:16.177 回答
2

你是对的,没有完美的答案。IEnumerable 只支持迭代,不保证枚举是可重复的。如果不调用 MoveNext 至少一次,您将无法确定枚举是否包含元素,并且一旦您这样做了,您就不能保证能够重用该枚举:IEnumerable.Reset 允许抛出 NotSupportedException。从http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx

“为 COM 互操作性提供了 Reset 方法。它不一定需要实现;相反,实现者可以简单地抛出 NotSupportedException。”

IEnumerable<T>.Count 和 IEnumerable<T>.Any 等扩展方法需要在幕后调用 MoveNext。有用的包装器,但不要回避这样一个事实,即在枚举不支持重置的(极少数)情况下,您可能会遇到问题。

于 2008-09-22T20:51:21.887 回答
0

使用这两种方法要注意的一点是,并非所有枚举都可以回滚,例如 System.Data.IDataReader 的所有实现只能运行一次。

foreach在这些情况下,只要您考虑到它甚至可能不会循环一次的事实,您就不会真正在循环中产生成本。

于 2008-09-22T20:43:48.723 回答
0

第一种方法有一个 Empty 扩展方法的简单实现:http: //signum.codeplex.com/SourceControl/changeset/view/25903#510468

于 2009-03-13T02:16:28.340 回答