为什么IOrderedEnumerable在过滤后不保留顺序

joh*_*y 5 3 c# linq

我已经创建了一个简化问题的方法.我有一个有序的IEnumerable,我想知道为什么应用where过滤器可以对对象进行排序

这不会编译,而它应该具有潜力

IOrderedEnumerable<int> tmp = new List<int>().OrderBy(x => x);
//Error Cannot Implicitly conver IEnumerable<int> To IOrderedEnumerable<int>
tmp = tmp.Where(x => x > 1);
Run Code Online (Sandbox Code Playgroud)

据我所知,如果来自IQueryable,例如使用linq到某个DB Provider,就没有gaurenteed执行顺序.

但是,在处理Linq To Object时会发生什么样的事件会导致对象无序,或者为什么不实现?

编辑

我理解如何正确地订购这不是问题.我的问题更多的是一个设计问题.对linq到对象的where过滤器应枚举给定枚举和应用过滤.那么为什么我们只能返回IEnumerable而不是IOrderedEnumerable?

编辑

澄清这个有用的时候.我正在根据代码中的条件构建查询,我想尽可能多地重用代码.我有一个返回OrderedEnumerable的函数,但是在应用了额外的地方之后我将不得不重新排序它,即使它将处于其原始的有序状态

Eri*_*ert 14

Rene的回答是正确的,但可以使用一些额外的解释.

IOrderedEnumerable<T>并不意味着"这是一个有序的序列".这意味着"这是一个已经应用了订购操作的序列,您现在可以ThenBy通过强制执行额外的订购要求来实现这一目标."

结果Where不允许您跟进ThenBy,因此您不能在需要的上下文中使用它IOrderedEnumerable<T>.

合理?

但是,当然,正如其他人所说,你几乎总是想先做过滤然后再做排序.这样你就不会花时间将物品整理成你要丢弃的物品.

当然,您必须先订购然后过滤; 例如,查询"女性演唱的前十首歌曲"以及"女性演唱的前十首歌曲"的查询可能非常不同!第一个是排序歌曲 - >进入前十 - >应用过滤器.第二种是应用过滤器 - >排序歌曲 - >进入前十名.

  • @ johnny5:如果你的逻辑只适用于`IOrderedEnumerable`,而不是'IEnumerable`,那只能是因为它需要使用`ThenBy` /`ThenByDescending` ...所以再次,你为什么要拆分排序进入"做一点,然后过滤,然后再做一些"?基本上听起来你的代码中可能存在设计问题,而你将责任归咎于LINQ. (2认同)

Ren*_*ogt 5

签名Where()是这样的:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
Run Code Online (Sandbox Code Playgroud)

所以这个方法IEnumerable<int>作为第一个参数.在IOrderedEnumerable<int>从返回的OrderBy工具IEnumerable<int>,所以这是没有问题的.

但正如你所看到的,Where返回一个IEnumerable<int>而不是一个IOrderedEnumerable<int>.这不能相互融合.

无论如何,该序列中的对象仍将具有相同的顺序.所以你可以这样做

IEnumerable<int> tmp = new List<int>().OrderBy(x => x).Where(x => x > 1);
Run Code Online (Sandbox Code Playgroud)

并得到你期望的序列.

但是,当然,您应该(出于性能原因)首先过滤您的对象,然后在需要排序的对象较少时对它们进行排序:

IOrderedEnumerable<int> tmp = new List<int>().Where(x => x > 1).OrderBy(x => x);
Run Code Online (Sandbox Code Playgroud)