在阅读以下问题之后,我正在挖掘一些差异: delegate.createdelegate()和仿制药:错误绑定到目标方法

我从巴里·凯利(Barry Kelly)找到了一些非常好的代码https://www.blogger.com/comment.g?blogid=8184237816669520763&postID=2109708553230166434

这里是(以加糖的形式:-)

using System;

namespace ConsoleApplication4
{
    internal class Base
    {
    }

    internal class Derived : Base
    {
    }

    internal delegate void baseClassDelegate(Base b);

    internal delegate void derivedClassDelegate(Derived d);


    internal class App
    {
        private static void Foo1(Base b)
        {
            Console.WriteLine("Foo 1");
        }

        private static void Foo2(Derived b)
        {
            Console.WriteLine("Foo 2");
        }

        private static T CastDelegate<T>(Delegate src)
            where T : class
        {
            return (T) (object) Delegate.CreateDelegate(
                                    typeof (T),
                                    src.Target,
                                    src.Method,
                                    true); // throw on fail
        }

        private static void Main()
        {
            baseClassDelegate a = Foo1; // works fine

            derivedClassDelegate b = Foo2; // works fine

            b = a.Invoke; // the easy way to assign delegate using variance, adds layer of indirection though

            b(new Derived());

            b = CastDelegate<derivedClassDelegate>(a); // the hard way, avoids indirection

            b(new Derived());
        }
    }
}

除了这条线(看起来很简单)外,我都了解所有这些。

b = a.invoke; //使用方差分配委派的简便方法,虽然增加间接层

谁能告诉我:

  1. 如何在不传递静态函数所需的参数的情况下调用Invoke。
  2. 当您从调用Invoke分配返回值时,何时在引擎盖下进行
  3. 巴里通过额外的间接意味着什么(在他的评论中)
有帮助吗?

解决方案

他没有打电话 Invoke (请注意缺乏 ()),他正在使用隐式代表创建来设置 b 等于新的 derivedClassDelegate 指向的实例 Invoke 的方法 a. 。其他间接是什么时候 b 被调用,调用 a.Invoke(new Derived()) 而不是只是 a(new Derived()).

使实际发生的事情更加明确:

baseClassDelegate a = Foo1; // works fine 

derivedClassDelegate b = Foo2; // works fine 

b = new derivedClassDelegate(a.Invoke); // the easy way to assign delegate using variance, adds layer of indirection though 

b(new Derived());

b = CastDelegate<derivedClassDelegate>(a); // the hard way, avoids indirection 

b(new Derived());

第一次打电话给 b 结果产生这样的链(为简单起见,消除了参数):

b() -> a.Invoke() -> Foo1()

第二个电话 b 结果:

b() -> Foo1()

然而

仅当您需要一个签名的代表来调用另一个(限制性较小)签名的代表时,才需要这一点。在他的示例中,您可以设置 b = Foo1 它会编译,但这并不能说明这一点。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top