デフォルトの場合に行う必要があるのは次のとおりです。
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ます。概念的な並べ替えの観点から、これは「このシーケンスのすべてのアイテムはこの種の目には等しいが、等しいオブジェクトが他の何かによってタイブレイクされるべきであると指定する場合は、そうする。
「noopsort」の別の考え方は、入力シーケンスのインデックスに基づいてアイテムを並べ替えることです。これは、アイテムがすべて「等しい」わけではないことを意味します。つまり、順序入力シーケンスが出力シーケンスの最終順序になり、入力シーケンスの各アイテムは常に前のアイテムよりも大きいため、「タイブレーカー」が追加されます。 「比較は何も行わず、その後の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();
}
}