複数の条件をもったソートを簡単に実装する

結論からいうと自分で実装しようとするとかなり大変です。いわゆる車輪の再発明ということになってしまいます。まじめにやればできるのですが、ほんとうに正しいかどうか検証するのに時間がかかります。

素直に C# で用意されているソートを使いこなすほうが、速度も速いでしょうし、信頼度も高いです。

下記がサンプルコードです。Form1 に button1 を配置して button1_Click(); を定義してください。

Excel などを使って目的のソートになっているか確認しながらご作業ください。「昇順/降順」「小さい順/大きい順」、あ~フレーズのバリエーションが多くて頭が混乱しますね。

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace myapp
{
	public partial class Form1 : Form
	{

		List<TheObject> TheList;

		public Form1()
		{

			InitializeComponent();

			TheList = new List<TheObject>();

			// テスト用のデータをつくる.
			TheList.Add( new TheObject( "Bravo",  3, 500 ));
			TheList.Add( new TheObject( "Alpha",  1, 100 ));
			TheList.Add( new TheObject( "Charie", 0, 300 ));
			TheList.Add( new TheObject( "Echo",   2, 200 ));
			TheList.Add( new TheObject( "Delta",  4, 400 ));

		}

		private void button1_Click( object sender, EventArgs e )
		{

			/*

			OrderBy「小さい順」「昇順」「小 → 大」「アルファベット」.
			0 1 2 3 4 (数値)
			A B C D E (文字列)

			OrderByDescendingt「大きい順」「降順」「大 → 小」「逆アルファベット」.
			4 3 2 1 0 
			E D C B A

			ThenBy 前のソートキーに従属しつつ、「小さい順」「昇順」「小 → 大」「アルファベット」.
			0 1 2 3 4
			A B C D E

			ThenByDescendingt 前のソートキーに従属しつつ、「大きい順」「降順」「大 → 小」「逆アルファベット」.
			4 3 2 1 0 
			E D C B A

			*/

			// リストをソートする. 優先度は Name, ID, Value.
			IOrderedEnumerable<TheObject> iOdrEnum = TheList
														.OrderBy          ( obj => obj.Name )
														.ThenBy           ( obj => obj.ID )
														.ThenByDescending ( obj => obj.Value );

			/*
			// リストをソートする. 優先度は Value, ID, Name.
			IOrderedEnumerable<TheObject> iOdrEnum = TheList
														.OrderBy          ( obj => obj.Value )
														.ThenBy           ( obj => obj.ID )
														.ThenBy           ( obj => obj.Name );
			*/

			/*
			// リストをソートする. 優先度は ID, Name, Value.
			IOrderedEnumerable<TheObject> iOdrEnum = TheList
														.OrderByDescending ( obj => obj.ID )
														.ThenBy            ( obj => obj.Name )
														.ThenByDescending  ( obj => obj.Value );
			*/

			// インタフェースから実物を取得する.
			List<TheObject> the_list_sorted = iOdrEnum.ToList();
	
			StringBuilder sb = new StringBuilder();

			for ( int n = 0; n < ( the_list_sorted.Count ); n++ )
			{

				String s = String.Format(
									"{0}\t{1}\t{2}",
									the_list_sorted[n].Name,
									the_list_sorted[n].ID,
									the_list_sorted[n].Value
									);

				sb.AppendLine( s );

			}

			// ソートの結果を表示する.
			MessageBox.Show( sb.ToString().Trim() );

		}
	}
}

リストの要素は下記のクラスになります。

using System;

namespace myapp
{
	public class TheObject
	{

		public String Name;
		public int    ID;
		public int    Value;

		public TheObject( String name, int id, int value )
		{
			this.Name  = name;
			this.ID    = id;
			this.Value = value;
		}

	}
}