假设有一种扩展方法,可根据SortMethod
枚举指定的几种排序类型(即按各种属性进行排序)对IQueryable进行排序。
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
是null
(即指定我不在乎值的顺序),那么有一种方法可以代替IEnumerator
值作为“排序”而不必执行实际排序?我希望能够调用此扩展,然后可能执行一些附加的
ThenBy
排序。 最佳答案
对于默认情况,您需要做的就是:
queryRes = values.OrderBy(a => 1);
这实际上将是一种无用的排序。由于OrderBy执行稳定排序,因此如果所选对象相等,则将维持原始顺序。请注意,由于这是
IQueryable
而不是IEnumerable
,因此查询提供程序可能无法执行稳定的排序。在这种情况下,您需要知道保持顺序是否重要,或者只说“我不在乎结果是什么顺序,只要可以在结果上调用ThenBy
即可。”允许您避免实际排序的另一种方法是创建自己的
IOrderedEnumerable
实现: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();
}
}
这样,您的查询可以是:
queryRes = new NoopOrder<AClass>(values);
请注意,以上类的结果是,如果存在对
ThenBy
的调用,则ThenBy
实际上将是顶级排序。实际上,它将后续的ThenBy
转换为OrderBy
调用。 (这不足为奇; ThenBy
将调用CreateOrderedEnumerable
方法,并且在此代码中调用OrderBy
,基本上将ThenBy
转换为OrderBy
。从概念上的排序角度来看,这是一种表示“所有在这种情况下,此序列中的项是相等的,但是如果您指定相等的对象应该被其他东西打破,则应这样做。另一种“无操作排序”的思考方式是,它根据输入序列的索引对项目进行排序。这意味着这些项不是全部“相等”,这意味着顺序输入序列将是输出序列的最终顺序,并且由于输入序列中的每个项始终大于其前面的项,因此添加了额外的“tiebreaker” ”比较将无济于事,从而使后续的
ThenBy
调用毫无意义。如果需要此行为,则比上一个更容易实现: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();
}
}