5

インターフェイスを実装する値型メソッドへのオープン インスタンス デリゲートを作成しようとすると、Delegate.CreateDelegate が失敗します。インスタンス メソッドは値型であるため、最初の引数は ref である必要があります。このため、一般的なデリゲート型を定義しましょう。

delegate T2 VF<T0, T1, T2>(ref T0 arg0, T1 arg1);

次に、int.ToString(string) へのオープン インスタンス デリゲートの作成に成功するが、int.Equals(int) へのオープン インスタンス デリゲートの作成に失敗するプログラムを次に示します。

class Program
{
    static void Main(string[] args)
    {
        var tos = typeof(int).GetMethod("ToString", new[] { typeof(string) });
        var tosopen = Delegate.CreateDelegate(
                          typeof(VF<int, string, string>), null, tos);
        // success!

        var eq = typeof(int).GetMethod("Equals", new[] { typeof(int) });
        var eqopen = Delegate.CreateDelegate(
                         typeof(VF<int, int, bool>), null, eq);
        // previous line fails with "Error binding to target method"
    }
}

これは int.Equals(int) が を実装しているためと思われますIEquatable<int>以下が機能することに注意してください。

var x = typeof(IEquatable<int>).GetMethod("Equals", new Type[] { typeof(int) });
var xopen = Delegate.CreateDelegate(
                typeof(Func<IEquatable<int>, int, bool>), null, x);
xopen(1,1); // returns true

しかし、これは最初の引数として渡された整数をボックス化するように見えるため、私が望んでいるものとはまったく異なります。また、 を比較したくありませんIEquatable<int>。具体的にメソッドを呼び出して、2 つの int を比較したいと考えています。

ここで何が間違っているかについて何か考えはありますか?

Microsoft Connect のバグがここで言及されましたが、これは直接関連していると思われますが、そのリンクは機能しなくなり、検索してもそのバグを見つけることができません。

編集:オーバーライドされたメソッドへのオープンインスタンスデリゲートを作成しようとすると同じ問題が発生するため、インターフェイスメソッドだけではないことに注意してください。

4

1 に答える 1

1

これは時間テストの一環として実行されました。お役に立てば幸いです。

    public delegate Boolean RefFunc<T>(ref T arg1, Object arg2);
    static void Main(string[] args)
    {
        double loops = 1e6;
        Random random = new Random();
        System.Reflection.MethodInfo m;
        Stopwatch stopwatch = new Stopwatch();
        Type type = typeof(double);

        double tmp;
        stopwatch.Reset();
        stopwatch.Start();
        var deligates = new Dictionary<Type, RefFunc<double>>();
        RefFunc<double> d;
        for (int ii = 0; ii < loops; ii++)
        {
            if (!deligates.TryGetValue(type, out d))
            {
                m = type.GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(Object) }, null);
                d = (RefFunc<double>)Delegate.CreateDelegate(typeof(RefFunc<double>), null, m);
                deligates[typeof(double)] = d;
            }
            tmp = Convert.ToDouble(random.Next(0, 100));
            d(ref tmp, Convert.ToDouble(random.Next(0, 100)));
        }
        stopwatch.Stop();
        Console.WriteLine("Delegate " + stopwatch.Elapsed.ToString());
        Console.WriteLine("Delegate " + (stopwatch.Elapsed.Ticks / loops).ToString());

        Console.WriteLine("");
    }

編集: 元の投稿の日付に気付きましたが、それでも他の人の時間を大幅に節約できます。

于 2016-03-03T03:11:56.817 に答える