C#学习教程:在不使用IOrderedEnumerable的情况下计算IOrderedEnumerable=>x);intcount=source.Count;//<--在不执行排序的情况下获取元素的数量详细版本:要确定IEnumerable中的元素数量,必须迭代所有元素。这可能是一个非常昂贵的操作。如果可以将IEnumerable转换为ICollection,则无需迭代即可快速确定计数。LINQCount()方法自动执行此操作。函数myEnumerable.OrderBy()返回一个IOrderedEnumerable。IOrderedEnumerable显然不能转换为ICollection,因此调用Count()将消耗整个事物。但是排序不会改变元素的数量,并且IOrderedEnumerable必须保留对其源的引用。因此,如果该源是一个ICollection,则应该可以在不使用IOrderedEnumerable的情况下确定计数。我的目标是有一个库方法,它接受一个带有n个元素的IEnumerable,然后检索,例如,位置n/2处的元素;我想避免迭代IEnumerable两次只是为了得到它的计数,但如果可能的话,我也想避免创建不必要的副本。这是我要创建的函数的框架publicvoidDoSomething(IEnumerablesource){intcount;//我们对源的处理取决于它的长度if(sourceisICollection){count=source.Count();//很好,我们可以使用ICollection.Count}elseif(源是IOrderedEnumerable){//TODO:找出这是否基于ICollection,//TODO:然后确定该ICollection的计数}else{//迭代overthesource可能很昂贵,//为避免迭代两次,制作源的副本source=source.ToList();count=source.Count();}//做一些事情}让我们想想这段代码实际上是怎样的上面的代码是什么样的:varsource=new[]{2,4,6,1,9}.OrderBy(x=>x);intcount=source.Count();它与intcount=Enumerable相同。Count(Enumerable.OrderBy(new[]{2,4,6,1,9},x=>x));可枚举。OrderBy(new[]{2,4,6,1,9},x=>x)被传递给Count扩展。您无法避免执行OrderBy。所以它是一个非流运算符,它在返回内容之前消耗所有源,这些内容将传递给Count。因此,避免遍历所有集合的唯一方法是避免OrderBy-在排序之前对项目进行计数。更新:您可以在任何OrderedEnumerable上调用此扩展方法-它将使用反射来获取包含源序列的OrderedEnumerable源字段。然后检查这个序列是否是一个集合,并使用Count而不执行排序:publicstaticclassExtensions{publicstaticintCount(thisIOrderedEnumerableordered){//你可以检查ordered是否是OrderedEnumerableTypetype=ordered.GetType();var标志=BindingFlags.NonPublic|BindingFlags.Instance;varfield=type.GetField("source",flags);varsource=field.GetValue(有序);如果(源是ICollection)返回((ICollection)源)。数数;返回有序计数();}}用法:varsource=new[]{2,4,6,1,9}.OrderBy(x=>x);intcount=source.Count();如果你想创建一个高性能的解决方案,我会考虑创建一个重载,它需要一个集合或IOrderedEnumerable等。所有“是”和“作为”类型检查和转换都不适合你正在创建的东西。你正在重新发明轮子。Linq的“Count()”函数可以为所欲为。此外,添加this关键字并使其成为一个漂亮的扩展方法,以取悦您自己和其他消费代码。DoSomething(此集合来源);DoSomething(此列表来源);DoSomething(这个IOrderedEnumerable来源);等等...另一种方法是实现一个实现IOrderedEnumerable的类。然后,您可以实现类成员,使常用的Linq扩展方法短路,并提供一个查看原始枚举的计数方法。以上就是C#学习教程:计算IOrderedEnumerable而不使用它共享的所有内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注——publicclassMyOrderedEnumerable:IOrderedEnumerable{privateIEnumerableOriginal;私有IOrderedEnumerable已排序;publicMyOrderedEnumerable(IEnumerableorig){Original=orig;排序=空;}privatevoidApplyOrder(FunckeySelector,IComparercomparer,booldescending){varbefore=Sorted!=null?已排序:原始;if(descending)Sorted=before.OrderByDescending(keySelector,comparer);elseSorted=before.OrderBy(keySelector,comparer);}#region接口实现publicIEnumeratorGetEnumerator(){returnSorted!=null?Sorted.GetEnumerator():Original.GetEnumerator();}IEnumeratorIEnumerable.GetEnumerator(){返回GetEnumerator();}publicIOrderedEnumerableCreateOrderedEnumerable(FunckeySelector,IComparercomparer,booldescending){varnewSorted=newMyOrderedEnumerable(Original);newSorted.ApplyOrder(keySelectparer,降序);返回新排序;}#endregionInterfaceImplementations//确保OrderBy返回正确的类型。//还有其他的OrderBy扩展方法变体,你必须短路publicMyOrderedEnumerableOrderBy(FunckeySelector){Console.WriteLine("Ordering");varnewSorted=newMyOrderedEnumerable(原始);newSorted.Sorted=(Sorted!=null?Sorted:Original).OrderBy(keySelector);返回新排序;}publicintCount(){Console.WriteLine("快速计数..");varcollection=OriginalasICollection;返回集合==null?Original.Count():collection.Count;}publicstaticvoidTest(){varnums=newMyOrderedEnumerable(Enumerable.Range(0,10).ToList());varnums2=nums.OrderBy(x=>-x);varz=nums.Count()+nums2.Count();}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
