当我认为我可以使用yield关键字时,我退后一步,看看它将如何影响我的项目.我总是最终返回一个集合而不是yeilding,因为我觉得保持yeilding方法状态的开销不会给我带来太大的影响.在几乎所有我返回集合的情况下,我觉得90%的时间,调用方法将迭代集合中的所有元素,或者将在整个集合中寻找一系列元素.
我确实理解它在linq中的用处,但我觉得只有linq团队正在编写这样复杂的可查询对象,这些对象的产生是有用的.
有没有人写过像linq这样的产品有用吗?
请注意,对于yield,您将迭代集合一次,但是当您构建列表时,您将迭代它两次.
以一个过滤器迭代器为例:
IEnumeratorFilter(this IEnumerator coll, Func func) { foreach(T t in coll) if (func(t)) yield return t; }
现在,你可以链接这个:
MyColl.Filter(x=> x.id > 100).Filter(x => x.val < 200).Filter (etc)
你的方法是创建(和折腾)三个列表.我的方法只迭代一次.
此外,当您返回集合时,您正在强制对您的用户进行特定实现.迭代器更通用.
我确实理解它在linq中的用处,但我觉得只有linq团队正在编写这样复杂的可查询对象,这些对象的产生是有用的.
只要它在.NET 2.0中实现,产量就很有用,早在人们想到LINQ之前很久.
我为什么要写这个函数:
IListLoadStuff() { var ret = new List (); foreach(var x in SomeExternalResource) ret.Add(x); return ret; }
当我可以使用yield时,无需充分理由就可以节省创建临时列表的工作量和复杂性:
IEnumerableLoadStuff() { foreach(var x in SomeExternalResource) yield return x; }
它还具有巨大的性能优势.如果您的代码恰好使用集合的前5个元素,那么使用yield通常会避免加载超过该点的任何内容.如果您构建一个集合然后返回它,您将浪费大量的时间和空间来加载您永远不需要的东西.
我可以继续下去....
我最近不得不以Expression类的形式表达数学表达式.在评估表达式时,我必须通过后序树行走来遍历树结构.为此,我实现了IEnumerable
public IEnumerator> GetEnumerator() { if (IsLeaf) { yield return this; } else { foreach (Expression expr in LeftExpression) { yield return expr; } foreach (Expression expr in RightExpression) { yield return expr; } yield return this; } }
然后我可以简单地使用foreach来遍历表达式.您还可以添加属性以根据需要更改遍历算法.
在以前的公司,我发现自己写这样的循环:
for (DateTime date = schedule.StartDate; date <= schedule.EndDate; date = date.AddDays(1))
使用一个非常简单的迭代器块,我能够将其更改为:
foreach (DateTime date in schedule.DateRange)
它使代码更容易阅读,IMO.
yield
是为C#2开发的(在C#3中的Linq之前).
在处理数据访问和重复计算时,我们在大型企业C#2 Web应用程序中大量使用它.
只要你有多个元素可以多次击中,集合就很棒.
然而,在许多数据访问场景中,您有大量的元素,您不一定需要在一个伟大的大集合中传递.
这基本上就是它SqlDataReader
所做的 - 它只是一个前向的自定义枚举器.
是什么yield
让你做的是快速,用最少的代码编写自定义枚举.
一切yield
都可以在C#1中完成 - 它只需要大量代码就可以完成.
Linq确实最大化了屈服行为的价值,但它肯定不是唯一的应用程序.