![](/img/trans.png)
[英]What is the difference (if any) between “yield” and “yield return” in C#?
[英]What is the exact difference between returning an IEnumerable instance and the yield return statement in C#
目前我正在使用一些通过迭代器应用延迟执行的库。 在某些情况下,我需要简单地“转发”收到的迭代器。 即我必须从被调用的方法获取IEnumerable<T>
实例并立即返回它。
现在我的问题:简单地返回收到的IEnumerable<T>
或通过循环重新产生它之间是否存在相关区别?
IEnumerable<int> GetByReturn()
{
return GetIterator(); // GetIterator() returns IEnumerable<int>
}
// or:
IEnumerable<int> GetByReYielding()
{
for(var item in GetIterator()) // GetIterator() returns IEnumerable<int>
{
yield return item;
}
}
阅读Jon Skeet关于C#迭代器的文章可能值得你去参考。 这是非常有益的。
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
它们是不同的。 例如,如果GetIterator()
声明为:
IEnumerable<int> GetIterator() {
List<int> result = new List<int>();
for(int i = 0; i < 1000; i++) {
result.Add(i);
}
return result;
}
如果不进行重新生成, GetIterator()
立即执行GetIterator()
和循环。 因此,答案取决于您如何实现GetIterator()
。 如果确定GetIterator()
将会屈服,那么重新产生它就没有意义了。
除了代码膨胀之外,我没有看到任何相关的区别。
两者之间没有任何相关的差异(除了可能的性能),因为你没有使用GetIterator()
的枚举器做任何事情。 如果您要对枚举器执行某些操作(例如过滤器),那么重新收益才有意义。
有一个相关的区别。
GetByReYielding()的执行将以延迟方式执行(因为它是迭代器块)。 如果您在GetByReturn()或GetByReYielding()中使用了一个参数并在运行时检查该参数是否为null(或进行了任何其他验证),则在调用GetByReturn()时立即执行此检查,但在调用GetByReYielding()时不立即执行此检查! 当迭代结果时,GetByReYielding()中的验证将以延迟方式执行。 - 这通常是“太晚了”。 看这里:
// Checks parameters early. - Fine. The passed argument will be checked directly when
// GetByReturn() is called.
IEnumerable<int> GetByReturn(IEnumerable<int> sequence)
{
if(null == sequence)
{
throw new ArgumentNullException("sequence");
}
return GetIterator();
}
// Checks parameters in a deferred manner. - Possibly not desired, it's "too" late. I.e. // when the
// result is iterated somewhere in a completely different location in your code the
// argument passed once will be checked.
IEnumerable<int> GetByReYielding(IEnumerable<int> sequence)
{
if(null == sequence)
{
throw new ArgumentNullException("sequence");
}
for(var item in GetIterator())
{
yield return item;
}
}
Skeet先生在http://msmvps.com/blogs/jon_skeet/archive/2010/09/03/reimplementing-linq-to-objects-part-2-quot-where-quot.aspx中解释了这个概念。 .Net中提供的标准查询运算符使用非延迟包装函数(例如Where())来检查参数,然后调用核心迭代器函数(正如我在GetByReturn()的实现中所示)。
我希望这有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.