C# 底层委托问题

发布于 2024-08-31 02:57:51 字数 2015 浏览 7 评论 0原文

在阅读 SO 中的以下问题后,我正在深入研究委托方差: 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.调用; // 使用方差分配委托的简单方法,增加了间接层,但

谁能告诉我:

  1. 如何在不传递静态函数所需的参数的情况下调用调用。
  2. 当您分配调用调用的返回值时,什么时候会发生
  3. Barry 的额外间接含义是什么(在他的评论中)

I was doing some digging around into delegate variance after reading the following question in SO : Delegate.CreateDelegate() and generics: Error binding to target method

I found a very nice bit of code from Barry kelly at
https://www.blogger.com/comment.g?blogID=8184237816669520763&postID=2109708553230166434

Here it is (in a sugared-up form :-)

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());
        }
    }
}

I understand all of it except this one (what looks very simple) line.

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

Can anyone tell me:

  1. how it is possible to call invoke without passing the param required by the static function.
  2. When is going on under the hood when you assign the return value from calling invoke
  3. What does Barry mean by extra indirection (in his comment)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

伪心 2024-09-07 02:57:51

他没有调用 Invoke(请注意缺少 ()),而是使用隐式委托创建将 b 设置为等于新的 >衍生类代理实例,指向aInvoke方法。额外的间接是,当调用 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 即可编译,但这并不能说明问题。

He isn't calling Invoke (note the lack of ()), he's using implicit delegate creation to set b equal to a new derivedClassDelegate instance that points to the Invoke method of a. The additional indirection is that when b is invoked, it calls a.Invoke(new Derived()) rather than just a(new Derived()).

To make what's actually happening more explicit:

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());

The first call to b results in a chain like this (parameters eliminated for simplicity):

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

The second call to b results in this:

b() -> Foo1()

However

This is only needed if you need a delegate of one signature to invoke a delegate of another (less restrictive) signature. In his example, you could just set b = Foo1 and it would compile, but that wouldn't illustrate the point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文