当前位置: 首页 > 编程语言 > C#

YieldOutsideLINQ有用吗?在

时间:2023-04-10 17:57:31 C#

LINQ之外共享输出有用吗?当我认为我可以使用yield关键字时,我退后一步,看看它会如何影响我的项目。我总是最终返回一个集合而不是yeilding,因为我不觉得保持yeilding方法状态的开销会太困扰我。在我返回集合的几乎所有情况下,我感觉90%的时间里,调用方法要么遍历集合中的所有元素,要么在整个集合中查找某个范围内的元素。我确实理解它在linq中的用处,但我觉得只有linq团队在编写如此复杂的可查询对象,以至于它们的生成是有用的。有没有人写过像linq有用的产品?我最近不得不以Expression类的形式表达数学表达式。在评估表达式时,我必须通过后序树遍历来遍历树结构。为此,我按如下方式实现了IEnumerable:publicIEnumerator>GetEnumerator(){if(IsLeaf){yieldreturnthis;}else{foreach(LeftExpression中的表达式expr){yieldreturnexpr;}foreach(RightExpression中的表达式expr){yieldreturnexpr;}yield返回这个;然后我可以简单地使用foreach来迭代表达式。您还可以根据需要添加属性来更改遍历算法。请注意,使用yield您将迭代集合一次,但是当您构建列表时,您将迭代它两次。以过滤器迭代器为例:IEnumeratorFilter(thisIEnumeratorcoll,Funcfunc){foreach(Ttincoll)if(func(t))yieldreturnt;现在,你可以链接这个:MyColl.Filter(x=>x.id>100).Filter(x=>x.val你的方法正在创建(和折腾)三个列表。我的方法只迭代一次。另外,当你返回集合时,你是在强迫你的用户做一个特定的实现。迭代器更通用。我确实理解它在linq中的用处,但我觉得只有linq团队在编写如此复杂的可查询对象,以至于它们的生成是有用的。只要在.NET2.0中实现,Yield就很有用,远早于人们想到LINQ。我为什么要写这个函数:IListLoadStuff(){varret=newList();foreach(varxinSomeExternalResource)ret.Add(x);返还;}没有充分的理由我可以使用yield节省了创建临时列表的工作量和复杂性:IEnumerableLoadStuff(){foreach(varxinSomeExternalResource)yieldreturnx;它还具有巨大的性能优势。如果您的代码碰巧使用集合的前5个元素,则使用yield通常会避免加载超过该点的任何内容。如果您构建一个集合然后返回它,您将浪费大量时间和空间加载您永远不需要的东西。我可以继续......在以前的公司,我发现自己写这样的循环:在schedule.DateRange中)它使代码更易于阅读,IMO。yield是为C#2开发的(在C#3中的Linq之前)。我们在处理数据访问和繁重的大型企业C#2Web应用程序时遇到了问题重新计算它在程序中用得很多。当你有多个元素可以被多次命中时,集合就很棒。但是,在许多数据访问场景中,你有大量的元素不一定需要在大型集合中传递.这基本上是SqlDataReader所做的-它只是一个前向自定义枚举器。使用它可以快速完成并使用最少的代码来编写你自己的自定义枚举器。所有yield都可以在C#1中完成-它只需要大量代码来获得它完成。Linq确实最大化了yield行为的价值,但它肯定不是唯一的应用程序。只要您的函数返回IEnumerable,就应该使用yield。不在.Net>3.0中。.Net2.0示例:publicstaticclassFuncUtils{publicdelegateTFunc();公共委托TFunc(A0arg0);公共委托TFunc(A0arg0,A1arg1);...publicstaticIEnumerableFilter(IEnumerablee,FuncfilterFunc){foreach(Teline)if(filterFunc(el))yieldreturnel;}publicstaticIEnumerableMap(IEnumerablee,FuncmapFunc){foreach(Teline)yieldreturnmapFunc(el);}。..我不确定C#对yield()的实现,但对于动态语言,它比创建整个集合更高效。在许多情况下,它可以轻松处理比RAM大得多的数据集。我是C#的超级粉丝。在大型本机框架中尤其如此,其中方法或属性通常会返回一个列表,该列表是另一个IEnumerable的子集。我看到的好处是:yield的另一个巨大好处是您的方法可能会返回数百万个值。如此之多,以至于只有在方法甚至可以返回之前构建List才有可能耗尽内存。使用yield,该方法可以创建和返回数百万个值,只要调用者也不存储每个值。所以它适合大规模的数据处理/聚合操作就我个人而言,我发现自己在正常的日常编程中并没有使用yield。但是,我最近开始使用RoboticsStudio示例,发现yield在那里被广泛使用,所以我也看到它与CCR(并发和协调运行时)一起使用,其中存在异步和并发问题。无论如何,我仍在努力解决这个问题。Yield很有用,因为它可以节省空间。编程中的大多数优化都是空间(磁盘、内存、网络)和处理之间的权衡。Yield作为一种编程构造,允许您按顺序多次迭代集合,而无需为每次迭代单独复制集合。思考这个例子:staticIEnumerableGetAllPeople(){returnnewList(){newPerson(){Name="George",Surname="Bush",City="Washington"},newPerson(){Name="Abraham",Surname="Lincoln",City="Washington"},newPerson(){Name="Joe",Surname="Average",City="NewYork"}};}staticIEnumerableGetPeopleFrom(thisIEnumerablepeople,stringwhere){foreach(varpersoninpeople){if(person.City==where)yieldreturnperson;产量中断;}staticIEnumerableGetPeopleWithInitial(thisIEnumerablepeople,stringinitial){foreach(varpersoninpeople){if(person.Name.StartsWith(initial))yieldreturnperson;产量中断;}staticvoidMain(string[]args){varpeople=GetAllPeople();foreach(varpinpeople.GetPeopleFrom("Washington")){//用washingtonites做点什么}foreach(varpinpeople.GetPeopleWithInitial("G")){//用首字母G做点什么}foreach(varp在people.GetPeopleWithInitial("P").GetPeopleFrom("NewYork")){//etc}}(显然,您不需要将yield与扩展方法一起使用,它只是创建了一个强大的范例来考虑数据)如您所见,如果您有这些“过滤”方法有很多(但它可以是任何一个,对一组人进行操作),您可以将它们中的许多链接在一起,而不需要为每个步骤额外存储。这是一种改进编程语言(C#)以更好地表达解决方案的方法。yield的第一个副作用是它会延迟过滤逻辑的执行,直到您真正需要它为止。因此,如果您创建一个IEnumerable类型的变量(带有yield)但从不对其进行迭代,您将永远不会执行逻辑或占用空间,这是一种强大而自由的优化。另一个副作用是yield在最低的公共集合接口(IEnumerable)上运行,这使得创建具有广泛适用性的类库代码成为可能。请注意,yield允许您以“惰性”方式执行操作。惰性是指IEnumberable中的下一个元素在实际请求该元素之前不会被评估。这允许您执行几个不同的操作。一是您可以生成一个无限长的列表,而无需实际进行无限计算。其次,您可以为函数应用程序返回一个枚举。这些函数仅在遍历列表时应用。我在非linq代码中得到了类似的东西(假设函数不在同一个类中):publicIEnumerableGetData(){foreach(Stringnamein_someInternalDataCollection){}}...publicvoidDoSomething(){foreach(StringvalueinGetData()){//...做一些不修改_someInternalDataCollection的值}}你必须小心不要无意中修改集合GetData()函数迭代,否则将抛出异常。产量通常非常有用。在其他支持函数式风格编程的语言中,它就是Ruby,所以它与LINQ相关联。相反,linq是函数式的,所以它使用yield。我有一个问题,我的程序正在为某些后台任务使用大量CPU。我真正想要的是仍然能够像平常一样编写函数,以便我可以轻松阅读它们(即整个线程与基于事件的参数)。如果它们花费过多的CPU,仍然有可能破坏这些功能。产量是完美的。我写了一篇关于这个的博客文章,源代码可以被所有人找到:)System.LinqIEnumerable扩展很棒,但有时你想要更多。例如,考虑以下扩展:publicstaticclassCollectionSampling{publicstaticIEnumerableSample(thisIEnumerablecoll,intmax){使用(varenumerator=coll.GetEnumerator());{while(enumerator.MoveNext()){yieldreturnenumerator.Current;intcurrentSample=rand.Next(max);for(inti=1;iyielding的另一个有趣的优点是调用者不能将返回值强制转换为原始集合类型和修改内部集合以上是C#学习教程:LINQ以外的输出有用吗?所有的内容分享,如果对大家有用,需要了解更多C#学习教程,希望大家多多关注---本文来自网络收集,不代表立场,如涉及侵权,请点击右边联系管理员删除,如需转载请注明出处: