收益在现实生活中有哪些应用?
我知道yield
的作用,并且已经看过一些示例,但是我无法想到现实生活中的应用程序,我们是否使用它来解决某些特定问题?
(理想情况下,某些问题无法通过其他方式解决)
解决方案
回答
实际上我在我的网站IdeaPipe上以非传统方式使用它
public override IEnumerator<T> GetEnumerator() { // goes through the collection and only returns the ones that are visible for the current user // this is done at this level instead of the display level so that ideas do not bleed through // on services foreach (T idea in InternalCollection) if (idea.IsViewingAuthorized) yield return idea; }
因此,基本上,它会检查查看该想法是否当前得到授权,如果返回,则返回该想法。如果不是,则将其跳过。这使我可以缓存构思,但仍将构思显示给授权的用户。否则,当它们仅每1小时重新排列一次时,我将不得不根据权限重新拉出它们。
回答
LINQ在Enumerable类上的运算符实现为使用yield语句创建的迭代器。它允许我们链接Select()和Where()之类的操作,而无需实际枚举任何内容,直到我们在循环中实际使用枚举器为止(通常通过使用foreach语句)。此外,由于如果我们决定停止中间收集,则在调用IEnumerator.MoveNext()时仅计算一个值,因此可以节省计算所有结果的性能。
迭代器还可以用于实现其他类型的惰性求值,其中仅在需要时才对表达式求值。我们还可以将yield用于更多喜欢的东西,例如协程。
回答
yield的另一个好用法是对IEnumerable的元素执行功能,并返回不同类型的结果,例如:
public delegate T SomeDelegate(K obj); public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action) { foreach (var i in list) yield return action(i); }
回答
一种有趣的用途是作为异步编程的一种机制,特别是对于需要多个步骤并且在每个步骤中需要相同数据集的任务。这方面的两个示例是Jeffery Richters AysncEnumerator的第1部分和第2部分。并发和协调运行时(CCR)也利用了该技术CCR迭代器。
回答
使用yield可以防止向下转换为具体类型。确保集合的使用者不操纵它很方便。
回答
我意识到这是一个老问题(乔恩·斯凯特之前?),但是我最近一直在考虑这个问题。不幸的是,目前的答案(我认为)并未提及yield语句的最明显优势。
yield语句的最大好处是,与使用标准列表相比,它允许我们使用非常有效的内存使用量来遍历非常大的列表。
例如,假设我们有一个数据库查询,该查询返回100万行。我们可以使用DataReader检索所有行并将它们存储在List中,因此需要list_size * row_size个字节的内存。
或者,我们可以使用yield语句创建一个Iterator,并且一次只能在内存中存储一行。实际上,这使我们能够对大型数据集提供"流"功能。
此外,在使用Iterator的代码中,我们使用了一个简单的foreach循环,并可以根据需要决定退出循环。如果我们确实要早点休息,则仅在需要前5行时就不必强制检索整个数据集。
关于:
Ideally some problem that cannot be solved some other way
yield语句不会为我们提供使用我们自己的自定义迭代器实现无法完成的任何工作,但是它省去了编写通常所需的复杂代码的麻烦。只有极少数的问题(如果有的话)不能解决不止一种方法。
以下是一些提供更多详细信息的最新问题和解答:
收益关键字的价值增加了吗?
产量在LINQ之外有用吗?