问题描述
假设有一个 SortMethod
枚举指定的扩展方法基于几种类型排序的订购一个IQueryable(即通过各种属性排序)。
Say there is an extension method to order an IQueryable based on several types of Sorting (i.e. sorting by various properties) designated by a SortMethod
enum.
public static IOrderedEnumerable<AClass> OrderByX(this IQueryable<AClass> values,
SortMethod? sortMethod)
{
IOrderedEnumerable<AClass> queryRes = null;
switch (sortMethod)
{
case SortMethod.Method1:
queryRes = values.OrderBy(a => a.Property1);
break;
case SortMethod.Method2:
queryRes = values.OrderBy(a => a.Property2);
break;
case null:
queryRes = values.OrderBy(a => a.DefaultProperty);
break;
default:
queryRes = values.OrderBy(a => a.DefaultProperty);
break;
}
return queryRes;
}
在的情况下 sortMethod
是空
(即它被指定,我不关心值的顺序),是有办法的,而不是由某些默认的属性排序,以而不是仅仅通过的IEnumerator
值通过为有序,而无需执行实际排序?
In the case where sortMethod
is null
(i.e. where it is specified that I don't care about the order of the values), is there a way to instead of ordering by some default property, to instead just pass the IEnumerator
values through as "ordered" without having to perform the actual sort?
我想调用这个扩展的能力,然后可能执行一些额外的 ThenBy
序。
I would like the ability to call this extension, and then possibly perform some additional ThenBy
orderings.
推荐答案
所有你需要的默认情况下,做的是:
All you need to do for the default case is:
queryRes = values.OrderBy(a => 1);
这将有效地成为一个空操作,排序。因为排序依据执行一个稳定的排序原来的订单将在事件所选择的对象相等进行维护。请注意,因为这是一个的IQueryable
而不是的IEnumerable
有可能为查询提供者不执行一个稳定的排序。在这种情况下,你需要知道它的重要的顺序进行维护,或者如果它合适,只是说:我不在乎什么样的顺序,结果是,只要我可以叫 ThenBy
的结果)。
This will effectively be a noop sort. Because the OrderBy performs a stable sort the original order will be maintained in the event that the selected objects are equal. Note that since this is an IQueryable
and not an IEnumerable
it's possible for the query provider to not perform a stable sort. In that case, you need to know if it's important that order be maintained, or if it's appropriate to just say "I don't care what order the result is, so long as I can call ThenBy
on the result).
另一种选择,即可以让你避免实际的排序是创建自己的 IOrderedEnumerable
实施
Another option, that allows you to avoid the actual sort is to create your own IOrderedEnumerable
implementation:
public class NoopOrder<T> : IOrderedEnumerable<T>
{
private IQueryable<T> source;
public NoopOrder(IQueryable<T> source)
{
this.source = source;
}
public IOrderedEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending)
{
if (descending)
{
return source.OrderByDescending(keySelector, comparer);
}
else
{
return source.OrderBy(keySelector, comparer);
}
}
public IEnumerator<T> GetEnumerator()
{
return source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return source.GetEnumerator();
}
}
随着你的查询可以是:
With that your query can be:
queryRes = new NoopOrder<AClass>(values);
请注意,上述类的后果是,如果有就 ThenBy
的 ThenBy
将有效通话是一个顶级的排序。正是这实际上是将后续的 ThenBy
到排序依据
电话。 (这不应该是不足为奇; ThenBy
将调用 CreateOrderedEnumerable
方法,并在那里这个code呼吁排序依据
,基本上翻了 ThenBy
到排序依据
,从来看一个概念分类来看,这是说,所有在这个序列中的项目是在这类面前人人平等的一种方式,但如果指定相等的对象应该由什么来tiebroken东西,那么这样做。
Note that the consequence of the above class is that if there is a call to ThenBy
that ThenBy
will effectively be a top level sort. It is in effect turning the subsequent ThenBy
into an OrderBy
call. (This should not be surprising; ThenBy
will call the CreateOrderedEnumerable
method, and in there this code is calling OrderBy
, basically turning that ThenBy
into an OrderBy
. From a conceptual sorting point of view, this is a way of saying that "all of the items in this sequence are equal in the eyes of this sort, but if you specify that equal objects should be tiebroken by something else, then do so.
无运算排序的思想的另一种方法是,它订单基于输入序列中的索引中的项目。这意味着该项目是不是所有的相等,这意味着该顺序输入序列的将的是输出序列的最后顺序,并且由于在输入序列中的每个项目总是比一个大在它之前,添加额外的抢七比较会做什么,做任何后续 ThenBy
调用毫无意义的。
Another way of thinking of a "no op sort" is that it orders the items based in the index of the input sequence. This means that the items are not all "equal", it means that the order input sequence will be the final order of the output sequence, and since each item in the input sequence is always larger than the one before it, adding additional "tiebreaker" comparisons will do nothing, making any subsequent ThenBy
calls pointless. If this behavior is desired, it is even easier to implement than the previous one:
public class NoopOrder<T> : IOrderedEnumerable<T>
{
private IQueryable<T> source;
public NoopOrder(IQueryable<T> source)
{
this.source = source;
}
public IOrderedEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending)
{
return new NoopOrder<T>(source);
}
public IEnumerator<T> GetEnumerator()
{
return source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return source.GetEnumerator();
}
}
这篇关于是否有可能把一个IEnumerable成IOrderedEnumerable不使用排序依据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!