WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

C# LINQ ThenByを使わないソート

今回のエンジニアブログを担当する加賀です。

C# 3.5でのLINQのThenByを使わないソートを紹介したいと思います。
今回のコードはVisual Studio 2010 Pro SP1、C# 3.5で確認しています。

なぜ使わない必要があるのか

Unity上での話にはなります。ThenByを使用すると、
iOS上で動作させたときに、ほとんどの型組み合わせでAOTエラーによってアプリが落ちてしまうからです。

落ちる型組み合わせは、多くの方がまとめられています。
iOS Linq」で検索してみるとたくさん見つかります。

今回のコード例はThenByを使っても落ちない型組み合わせですが、
ThenByで値型(intやstructなど)で比較する場合は落ちるので、ThenByを使わない方法で実装する必要があります。

ThenByを使ったソート

最初に、普通にThenByを使用したコードです。
コード例は、複数の文字列を短い順で並べて、同じ長さの場合はその中で昇順で並べるコードです。

using System.Linq;  
using System;  
  
public class EntryPoint {  
  public static void Main () {  
    string[] keywords = { "for", "in", "if", "while",   
                  "public", "static", "var", "using" };  
  
    var query = keywords  
      // 文字列を短い順で並べる  
      .OrderBy (keyword => keyword.Length)  
      // さらに昇順で並べる  
      .ThenBy (keyword => keyword);  
  
    foreach (string fruit in query) {  
      Console.WriteLine (fruit);  
    }  
    Console.ReadLine ();  
  }  
}  

ThenByを使わないソート

今度はThenByを使わないコードです。
変更点のみの表示です。

var query = keywords  
  // 文字列の長さでグループ化する  
  .GroupBy (keyword => keyword.Length)  
  // グループを文字列の長さの昇順で並び替える  
  .OrderBy (g => g.Key)  
  // 各グループ内で並び替えた結果を1つのストリームにする  
  .SelectMany (g => g  
    // グループ内で文字列を昇順で並び替える  
    .OrderBy (keyword => keyword)  
  );  

まとめ

処理回数が増えている気がしますが、もっといいやり方ないかなあと思います。
普通にThenByが使えればいいのですが、Unityがあまり対応する気がないようなので使わないこの方法を実装せざるを得ません。
でも第3条件以降も使いたいなら、この方法が有効かもしれません。