【问题标题】:C# Delegate under the hood questionC# Delegate under the hood 问题
【发布时间】:2010-05-06 00:50:18
【问题描述】:

在阅读了 SO 中的以下问题后,我正在研究委托差异:Delegate.CreateDelegate() and generics: Error binding to target method

我从 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. 当您从调用调用分配返回值时,幕后发生了什么
  3. 巴里所说的额外间接是什么意思(在他的评论中)

【问题讨论】:

    标签: c# delegates generic-variance


    【解决方案1】:

    他没有调用Invoke(请注意缺少()),他使用隐式委托创建将b 设置为等于指向@987654326 的Invoke 方法的新derivedClassDelegate 实例@。额外的间接性是当调用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 并且它会编译,但这并不能说明这一点。

    【讨论】:

    • @Ted:如果这回答了您的问题,请接受它作为答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2022-12-20
    相关资源
    最近更新 更多