Have sort() use culture info when sorting custom IComparable
I have a class like this:
public class Item : IComparable
{
public Type cType { get; set; }
public object cData { get; set; }
public Item(Type cType, object cData)
{
this.cType = cType;
this.cData = cData;
}
public int CompareTo(object obj)
{
if (obj == null) return 1;
var otherItem = Convert.ChangeType(obj, cType);
var ownItem = Convert.ChangeType(cData, cType);
if (typeof(string) == cType)
{
var res = string.Compare((string)ownItem, (string)otherItem, false, new CultureInfo("sv-SE"));
return res;
}
if (otherItem is IComparable cmp)
{
return cmp.CompareTo(ownItem);
}
else
{
return -1;
}
}
}
and a List of this Item, like this:
List<Item> Items = new List<Item>();
I know that there's some exception-handling missing here, but for the purpose of keeping this post short I'm leaving that out. I need to sort this list by the cData in my Item, this is how I'm trying to do that:
Items.Sort((x, y) => x.CompareTo(y.cData)
This works fine for items not affected by Culture information, but if the cData is a string containing some culture specific characters the sorting goes wrong. For example: if I have this list of names (strings) in my list:
Tord
Viktor
Örjan
Uno
and try to sort it, it returns:
Örjan
Tord
Uno
Viktor
this is wrong, the Swedish character 'ö' should appear last in the alphabet, and the expected outcome would be:
Tord
Uno
Viktor
Örjan
What am I doing wrong here? and how can I achieve the expected outcome?
EDIT #1: the Comparison overload of .Sort() is needed as this function only acts as a part in an larger system that uses it. I should probably have said that in the original question.
Lets say that I have an other class looking like this:
public class ItemCollection
{
public Dictionary<string, Item> SortingValues;
public string SomeColectionInfo;
}
I got a List of this class, ItemCollection:
List<ItemCollection> AllCollections = new List<ItemCollection>();
Finally I got a function, that are to sort the collections based on the one values of the items that they are holding:
void SortCollectionsOn(string Attribute)
{
AllCollections.Sort((x, y) => (x.SortingValues.ContainsKey(Attribute) ? x.SortingValues[Attribute] : new Item(typeof(string), "")).CompareTo(y.SortingValues.ContainsKey(Attribute) ? y.SortingValues[Attribute] :""));
}
I need to use the overload for this to work as some items don't have the attribute i'm sorting on.
this way I can sort on a attribute existing in a item. This is working until culture info is introduced. I didn't include this in my original question as i suspect that the problem lays in the cultural info.
Solution 1:
For some reason the function String.Compare() where not returning the correct result with the parameters given in the above question. Adding an CompareOption solved this problem. By adding CompareOptions.OrdinalIgnoreCase the expected results are returned.
this is what the line should look like:
var res = String.Compare((Data.ToString()), (otherItem.Data.ToString()), _culture, CompareOptions.OrdinalIgnoreCase);