概要
2022年11月に.NET 7とC# 11がリリースされました。
.NET 6でもいくつかのLINQメソッドが追加されましたが、.NET 7でも2つほどLINQメソッドが追加されています。
この投稿では、.NET 7でLINQに追加されたメソッドであるOrderとOrderDescendingについて紹介します。
なお昨年、.NET 6で追加されたメソッドはこちらをどうぞ!
OrderとOrderDescending
OrderメソッドとOrderDescendingメソッドは、要素自身を比較して、IEnumerable<T>
の要素を並べ替えたIEnumerable<T>
(正確にはIOrderedEnumerable<T>
)を返すLINQのメソッドです。
「要素の並べ替え」と聞くと、OrderByメソッドとOrderByDescendingメソッドをイメージする方も多いと思います。
.NET 6以前でも、OrderByメソッドとOrderByDescendingメソッドを次のように使うことで、配列を昇順・降順に並び替えたIEnumerable<T>
(正確にはIOrderedEnumerable<T>
)を生成することができます。
下記のコード例では、並べ替えのkeySelectorとして、要素をそのまま返すデリゲートを渡しています。
var arrayNumber = new[] { 4, 5, 1, 3, 2 };
// ↓は1, 2, 3, 4, 5というIOrderedEnumerable<int>
var sortedNumber = arrayNumber.OrderBy(e => e);
// ↓は5, 4, 3, 2, 1というIOrderedEnumerable<int>
var sortedDescNumber = arrayNumber.OrderByDescending(e => e);
var arrayMessage = new[] { "b", "a", "aa", "ab", "ba", "bb", "aaa" };
// ↓はa, aa, aaa, ab, b, ba, bbというIOrderedEnumerable<string>
var sortedMessage = arrayMessage.OrderBy(e => e);
// ↓はbb, ba, b, ab, aaa, aa, aというIOrderedEnumerable<string>
var sortedDescMessage = arrayMessage.OrderByDescending(e => e);
最新の.NET 7では、新たに加わったOrderメソッドとOrderDescendingメソッドを使うことで、上記のようにIEnumerable<T>
の要素で、keySelectorを引数に渡すことなく、要素を昇順・降順に並び替えることができます。
数字の配列やリストを並び替える、という処理は頻出していたと思います。その際のコードが簡潔になりましたね。
var arrayNumber = new[] { 4, 5, 1, 3, 2 };
// ↓は1, 2, 3, 4, 5というIOrderedEnumerable<int>
var sortedNumber = arrayNumber.Order();
// ↓は5, 4, 3, 2, 1というIOrderedEnumerable<int>
var sortedDescNumber = arrayNumber.OrderDescending();
var arrayMessage = new[] { "b", "a", "aa", "ab", "ba", "bb", "aaa" };
// ↓はa, aa, aaa, ab, b, ba, bbというIOrderedEnumerable<string>
var sortedMessage = arrayMessage.Order();
// ↓はbb, ba, b, ab, aaa, aa, aというIOrderedEnumerable<string>
var sortedDescMessage = arrayMessage.OrderDescending();
Orderメソッド・OrderDescendingメソッドのオーバーロードを以下に示します。IComparer<T> comparer
を引数にとるオーバーロードもあります。
public static System.Linq.IOrderedEnumerable<T> OrderDescending<T>(this System.Collections.Generic.IEnumerable<T> source)
public static System.Linq.IOrderedEnumerable<T> OrderDescending<T>(this System.Collections.Generic.IEnumerable<T> source, System.Collections.Generic.IComparer<T>? comparer)
public static System.Linq.IOrderedEnumerable<T> Order<T>(this System.Collections.Generic.IEnumerable<T> source)
public static System.Linq.IOrderedEnumerable<T> Order<T>(this System.Collections.Generic.IEnumerable<T> source, System.Collections.Generic.IComparer<T>? comparer)
メソッドの返り値型がIOrderedEnumerable<T>
です。そのため、返り値はThenByとThenByDescendingを呼び出せます。
OrderとOrderDescendingは、他のLINQメソッドと同様に、IEnumerable自身に副作用があるわけではないことに注意してください。
LINQではないList<T>
型のSortメソッドは副作用があり、Sortメソッドを呼び出したリスト自体の要素が並び替えられます。
OrderとOrderDescendingの内部実装では、OrderByおよびOrderByDescendingを利用しています。
内部では、OrderByおよびOrderByDescendingの引数として、引数をそのまま返すデリゲートを渡しています。
https://github.com/dotnet/runtime/blob/v7.0.0/src/libraries/System.Linq/src/System/Linq/OrderBy.cs#L25-L26
https://github.com/dotnet/runtime/blob/v7.0.0/src/libraries/System.Linq/src/System/Linq/OrderedEnumerable.cs#L247
まとめ
.NET 7でOrderとOrderDescendingがLINQメソッドとして追加されました。
OrderとOrderDescendingを使うことで、数値の配列・リストの並び替えなどがより簡潔に記述できるようになりましたね。