カスタム IComparer 実装の奇妙な動作に出くわし、それを修正して期待される動作を得る方法を理解できないようです。
指定した Int32 値で Guid の最初の 4 バイトを上書きできる System.Guid の拡張メソッドを提供する静的クラスを作成しました。これは、人口の多いデータベース テーブルのインデックスに適したセミシーケンシャル Guid を作成できるようにする目的で行われます。
public static class GuidExt
{
public static Guid Sequence(this Guid obj, int index)
{
byte[] b = obj.ToByteArray();
BitConverter.GetBytes(index).CopyTo(b, 0);
return new Guid(b);
}
}
非常に簡単で、期待どおりに機能します。
私が作成したカスタム Comparer クラスは、Guid の挿入された Int32 部分の昇順で Guid を並べ替えることができるように設計されています。実装は次のとおりです。
public class GuidSequenceComparer : IComparer<Guid>
{
public int Compare(Guid x, Guid y)
{
var xBytes = x.ToByteArray();
var yBytes = y.ToByteArray();
byte[] xIndexBytes = new byte[4];
for (int i = 0; i < 4; i++)
{
xIndexBytes[i] = xBytes[0];
}
byte[] yIndexBytes = new byte[4];
for (int i = 0; i < 4; i++)
{
yIndexBytes[i] = yBytes[i];
}
var xIndex = BitConverter.ToInt32(xIndexBytes, 0);
var yIndex = BitConverter.ToInt32(yIndexBytes, 0);
return xIndex.CompareTo(yIndex);
//// The following was used to test if any sort was being performed
//// and reverses the ordering (see below paragraph)
// if (xIndex > yIndex)
// {
// return -1;
// }
// if (xIndex < yIndex)
// {
// return 1
// }
// return 0;
}
}
List でこのカスタム比較子を使用すると、並べ替えは実行されますが、List オブジェクト内のインデックス位置が並べ替えられます。なぜこれが起こっているのかわかりませんが、コメントアウトされたセクションに示されているように比較の結果を逆にすることで確認しました.Guid内のint値ではなく、既存の位置に基づいてリストの順序を逆にしただけです.リスト内。なぜこれが起こっているのか、私は完全に迷っています。
動作を試して再現したい場合は、コンソール アプリ内で使用した簡単なテストを次に示します。
List<Guid> guidList = new List<Guid>();
guidList.Add(Guid.NewGuid().Sequence(5));
guidList.Add(Guid.NewGuid().Sequence(3));
guidList.Add(Guid.NewGuid().Sequence(8));
guidList.Add(Guid.NewGuid().Sequence(1));
Console.WriteLine("unsorted:");
foreach (Guid item in guidList)
{
Console.WriteLine(item);
}
guidList.Sort(new GuidSequenceComparer());
Console.WriteLine("sorted:");
foreach (Guid item in guidList)
{
Console.WriteLine(item);
}
Console.ReadLine();