Ответ 1
Все, что вам нужно сделать для случая по умолчанию:
queryRes = values.OrderBy(a => 1);
Это будет эффективно сортировать noop. Поскольку 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
. С точки зрения концептуальной сортировки это это способ сказать, что "все элементы в этой последовательности равны в глазах такого рода, но если вы укажете, что равные объекты должны быть привязаны чем-то другим, тогда сделайте это.
Другой способ мышления "no op sort" заключается в том, что он упорядочивает элементы, основанные на индексе входной последовательности. Это означает, что элементы не все "равны", это означает, что последовательность ввода порядка будет окончательным порядком выходной последовательности, и поскольку каждый элемент во входной последовательности всегда больше, чем предыдущий, добавляет дополнительный "тай-брейк" "сравнения ничего не сделают, делая любые последующие вызовы 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();
}
}