I've stumbled into some odd behavior of a custom IComparer implementation and can't seem to figure out how to correct it and get the expected behavior.
I created a static class providing an extension method to System.Guid that allows the first 4 bytes of a Guid to be overwritten with a specified Int32 value. This is done for the purpose of allowing creation of semi-sequential Guids which are index-friendly for high population database tables.
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);
}
}
Pretty straight forward and works exactly as expected.
The custom Comparer class I've created is designed to allow Guids to be sorted in ascending order of the inserted Int32 portion of a Guid. The implementation is as follows:
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;
}
}
When I use this custom comparer on a List, it does perform a sort, but it sorts the index position within the List object! No idea why this is happening but I confirmed it by reversing the results of the comparison as shown in the commented out section and it simply reversed the order of the List, not based on the int values within the Guid, but based on the existing positions within the List. I'm completely lost as to why this is happening.
Here's the simple test I used within a console app, if you would like to try and recreate the behavior.
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();