I am working with .Net Framework 4.8 and C# 5.0
I am using SortedSet class objects in my code. They are are defined as
SortedSet<Tuple<int, MyEnum1, MyStruct>> sortedSet1;
SortedSet<Tuple<int, MyEnum2, MyStruct>> sortedSet2;
The struct MyStruct implements a CompareTo() method.
I only wish to compare the tuples according to the first item, Item1. I can initialize these sorted sets as:
sortedSet1 = new SortedSet<Tuple<int, MyEnum1, MyStruct>>(new MyCustomComparer());
where:
private class MyCustomComparer : Comparer<Tuple<int, MyEnum1, MyStruct>>
{
public override int Compare(Tuple<int, MyEnum1, MyStruct> x, Tuple<int, MyEnum1, MyStruct> y)
{
// by int value only
return x.Item1.CompareTo(y.Item1);
}
}
and repeat the same comparer for sortedSet2, etc.
As I may have several of these sorted sets, I wish to avoid duplicating the custom comparers. I am therefore looking for a way to use a single comparer for all these types of sorted sets. I have tried a number of approaches but I cannot seem to be able to create a single comparer that would work for all these sorted sets. So far, the closest I have found online is the following:
public class MyCustomComparer<T> : IComparer
{
private int itemPosition;
private int multiplier = -1;
public MyCustomComparer(int component) : this(component, true)
{ }
public MyCustomComparer(int component, bool descending)
{
if (! descending) multiplier = 1;
if (component <= 0 || component > 6)
throw new ArgumentException("The component argument is out of range.");
itemPosition = component;
}
public int Compare(object x, object y)
{
var tX = x as Tuple<T1, T2, T3>;
if (tX == null)
{
return 0;
}
else
{
var tY = y as Tuple<T1, T2, T3>;
switch (itemPosition)
{
case 1:
return Comparer<T1>.Default.Compare(tX.Item1, tY.Item1) * multiplier;
case 2:
return Comparer<T2>.Default.Compare(tX.Item2, tY.Item2) * multiplier;
case 3:
return Comparer<T3>.Default.Compare(tX.Item3, tY.Item3) * multiplier;
default:
return Comparer<T1>.Default.Compare(tX.Item1, tY.Item1) * multiplier;
}
}
}
This code will not work with the initialization
sortedSet1 = new SortedSet<Tuple<int, MyEnum1, MyStruct>>(new MyCustomComparer<Tuple<int, MyEnum1, MyStruct>>(1));
because the generic parameters T1, T2, T3 are unknown.
I have tried modifying the above code to
public class MyCustomComparer<T1, T2, T3> : IComparer
{ ... }
but then my initalization
sortedSet1 = new SortedSet<Tuple<int, MyEnum1, MyStruct>>(new MyCustomComparer<T1,T2,T3>(1));
fails to work. I get errors CS1502 and CS1503:
Argument 1: cannot convert from 'MyCustomComparer<int,MyEnum1,MyStruct>' to 'System.Collections.Generic.IComparer<System.Tuple<int,MyEnum1,MyStruct>>'
I have tried many other variations along these lines but nothing seems to work. I would like to think that this can be accomplished but I cannot seem to find a way to do this. Any help would be greatly appreciated. Thank you.