4

C#ジェネリックとデリゲートについて質問があります:

最初に一般的な質問について説明します---デリゲートのコレクションが必要です。これらのデリゲートは同様の形式である必要があります。たとえば、すべてのデリゲートは次の形式である必要があります。同じタイプの2つのパラメーターを取得し、intを返します。これらのデリゲートをモデル化する最良の方法は、ジェネリックデリゲートを使用することだと思います。

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

しかし、どうすれば異なるタイプのMyFunctionDelのコレクションを作成できますか?私はこれを宣言することはできません:

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

そして第二に、これが私が実際にやろうとしていることです。私がやろうとしていることは、上記の質問で解決できます。しかし、あなたは別の解決策を与えることができます。

コレクションのような構造を作成しました。これは、あらゆるタイプのデータを保持できます。ただし、構造内のすべてのデータは同じタイプである必要があります。残念ながら、この構造は歴史的な理由から一般的ではありません。この構造にはCompareメソッドがあります。

しかし今、私はいくつかの特定のタイプのためにカスタマイズされた比較器を提供する必要があります。そして、私が望む動作は次のとおりです。構造には、データのタイプに対応するものがある場合はカスタマイズされた比較器が使用され、それ以外の場合は元のCompareメソッドが使用されます。これが私のデモコードです:

/*
 *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's 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);
    }
}

コメント、提案、洞察は大歓迎です!君たちありがとう。

4

3 に答える 3

2

デリゲートを作成Dictionary<Type, Delegate>してキャストし、要求されたときにタイプを修正できます。プレーンではなく、ヘルパークラスに従うことを検討してください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;
        }
    }
}

これで、次を使用できます。

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

var comparison = CustomizedComparers.GetComparison<T>();
return comparison(a, b);
于 2012-07-30T17:41:50.123 に答える
0

あなたはこのようにすることができます:

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.
于 2015-01-07T19:31:15.330 に答える
0

あなたが本当にやりたいことは、比較関数を型シグネチャの一部にしようとするのではなく、辞書のコンストラクターへのデリゲートとして渡すことだと思います。

于 2012-07-30T17:44:36.530 に答える