1
140
在处理递归定义的结构时,仔细考虑使用“yield return”是一个好主意。例如,我经常看到:
看起来非常合理的代码,但它存在性能问题。假设这棵树很深。然后至多会有O(H)嵌套迭代器构建。在外部迭代器上调用“moveNext”,然后对moveNext进行o(h)嵌套调用。因为它对一个包含n个项的树执行O(n)次操作,这使得算法成为O(hn)。由于二叉树的高度是lg n<=h<=n,这意味着算法在时间上最好是o(n lg n),最坏是o(n^2),在堆栈空间上最好是o(lg n),最坏是o(n)。它在堆空间中是O(H),因为每个枚举器都分配在堆上。(在C的实现中,我知道;一致的实现可能具有其他堆栈或堆空间特性。) 但是迭代树的时间可以是O(n),堆栈空间可以是O(1)。你可以这样写:
它仍然使用收益率回报,但更聪明。现在我们在时间上是O(n),在堆空间上是O(h),在堆栈空间上是O(1)。 进一步阅读:参见韦斯·戴尔关于这一主题的文章: http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx |
2
56
我可以考虑几个案例,例如:
|
3
32
要认识到的关键是
换句话说,当您不需要对序列进行惰性评估时,可以跳过使用
注意大多数LINQ语句如何返回
|
4
23
这里有很多很好的答案。我要加上一个:对于已经知道值的小集合或空集合,不要使用yield返回:
|
5
17
埃里克·利珀特提出了一个好观点(糟糕的是C没有 stream flattening like Cw )我要补充的是,有时由于其他原因,枚举过程是昂贵的,因此如果您打算多次迭代IEnumerable,那么应该使用一个列表。
例如,linq-to对象建立在“yield-return”之上。如果您编写了一个缓慢的LINQ查询(例如,将一个大列表过滤成一个小列表,或者进行排序和分组),那么调用
如果你在“收益回报”和
另一个不使用“收益率返回”的原因是如果交错操作是危险的。例如,如果您的方法看起来像这样,
如果由于调用方所做的某些事情而导致myCollection发生变化,则这是危险的:
|
6
6
我会避免使用
一个副作用可能是修改系统,这种情况可能发生在
我的经验法则(再一次,现在…)是:
|
7
5
当您需要随机访问时,yield将是限制/不必要的。如果您需要访问元素0,然后访问元素99,那么您已经基本上消除了延迟评估的有用性。 |
8
5
一个可能会让您抓到的问题是,如果您正在序列化一个枚举的结果,并通过网络发送它们。因为执行会延迟到需要结果为止,所以您将序列化一个空枚举并将其发送回,而不是发送您想要的结果。 |
9
2
如果不希望代码块返回迭代器以顺序访问底层集合,则不需要
|
10
2
我必须维护一堆代码,这些代码来自一个完全沉迷于收益率返回和IEnumerable的人。问题是,我们使用的许多第三方API以及我们自己的许多代码都依赖于列表或数组。所以我不得不这样做:
不一定很糟糕,但处理起来有点烦人,而且在某些情况下,它会导致在内存中创建重复的列表,以避免重构所有内容。 |
11
0
如果要定义一个Linq-Y扩展方法,在该方法中包装实际的Linq成员,那么这些成员通常不会返回迭代器。不需要自己通过迭代器屈服。 除此之外,使用yield定义一个“流式”可枚举(在jit基础上进行评估)并不会遇到太多麻烦。 |
Emopusta · 从后端到前端的图像路径不工作 2 年前 |
Asdrubal Hernandez · Linq查询特定数组索引出错 2 年前 |
Niyazi Babayev · 如何在表达式中动态应用表达式? 2 年前 |
Dansih · .Net核心自定义身份验证方案 2 年前 |
lolorekkk · 面板插入。NET WinForm 2 年前 |