Is it possible to declare a collection of many common delegates with different types?

I have a question about C # generators and delegation:

First, I describe the general question: I need a set of delegates, these delegates should have a similar form, for example, all my delegates should have the form: take two parameters of the same type and return an int. I think the best way to model these delegates is to use a generic delegate:

public delegate int MyFunctionDel <T> (T a, T b); 

But how can I create a MyFunctionDel collection with a different type? I can not declare this:

 List<MyFunctionDel <T>> mylist; //Compile error: cannot find type T 

And secondly, this is what I'm actually trying to do. What I'm trying to do can be resolved by the above question. But you can give alternative solutions.

I wrote a collection structure: it can store any type of data. But all the data in the structure must be of the same type. Unfortunately, this structure is not common for some historical reason. This structure has a comparison method.

But now I need to provide individual mappings for a specific type. And the behavior I want is: struture uses a configured match if it has one data type, otherwise the original Compare method is used. Here is my demo code:

 /* *This piece of code demonstates my idea, but never works */ static class Program { [STAThread] static void Main() { MyStructure s = new MyStructure (); //create a customized comparer using Comparison<T> generic delegate Comparison <string> myStirngComparer = (x , y)=> { return -x.CompareTo(y); }; s.CustomizedComparers[typeof(string)] = myStirngComparer; System.Console.WriteLine (s.Compare("a" , "b")); //I am expecting the result to be 1 } } class MyStructure { //For simplicity, I won't put storage related code here public int Compare (object o1, object o2) { //let suppose o1 and o2 are always of same type switch (o1.GetType()) { case TypeCode.Single: return Compare<Single> ((Single)o1 , (Single)o2); case TypeCode.Double: return Compare<Double> ((Double)o1 , (Double)o2); case TypeCode.String: return Compare<String> ((String)o1 , (String)o2); //and so on..... } return 0; } //NOTE: code below won't work //But my logic is: use a Dictionary to store a map from "Type" to "Comparison<T>" //When doing the comparison, we first examine if there exists one Comparison<T> for //Type T in the Dictionary //Compile failed here public Dictionary <Type , Comparison<T> > CustomizedComparers = new Dictionary <Type , Comparison<T> > (); private int Compare<T> (T a , T b) { if (CustomizedComparers.ContainsKey(typeof(T))) { Comparison<T> comp = CustomizedComparers[typeof(T)]; return comp (a , b); } else return Comparer<T>.Default.Compare(a, b); } } 

Any comments, suggestions and ideas are welcome! Thanks guys.

+4
source share
3 answers

You can create a Dictionary<Type, Delegate> and give delegates the correct type when they are requested. Consider the following helper class instead of plain Dictionary<Type, Delegate> :

 public class ComparersCollection { private readonly Dictionary<Type, Delegate> _comparers = new Dictionary<Type,Delegate>(); public void OverrideComparison<T>(Comparison<T> comparison) { if(comparison == null) { _comparers.Remove(typeof(T)); } else { _comparers[typeof(T)] = comparison; } } public Comparison<T> GetComparison<T>() { Delegate comparison; if(_comparers.TryGetValue(typeof(T), out comparison)) { return (Comparison<T>)comparison; } else { return Comparer<T>.Default.Compare; } } } 

Now you can use:

 Comparison <string> myStringComparer = (x, y) => -x.CompareTo(y); s.CustomizedComparers.OverrideComparison(myStringComparer); 

and

 var comparison = CustomizedComparers.GetComparison<T>(); return comparison(a, b); 
+2
source

I think that you really want to pass the comparison function as a delegate to the dictionary constructor, and not try to make it part of a type signature.

0
source

You can do it as follows:

 static class Comparison { static class Of<T> { static public readonly Func<T, T, int> Compare; static Of() { var type = typeof(T); if(type == typeof(string)) { Comparison.Of<T>.Compare = (Func<T, T, int>)(object)new Func<string, string, int>((x, y) => x.CompareTo(y)); } else if(type == typeof(int)) { //... can generated dynamically with expression or dynamicmethod. } else { throw new NotSupportedException(); } } } static public int Compare<T>(T x, T y) { return Comparison.Of<T>.Compare(x, y); } } var a = "1"; var b = "2"; Comparison.Compare(a, b); //generic parameter is infered. 
0
source

All Articles