【问题标题】:Difference between Delegate.Invoke and Delegate()Delegate.Invoke 和 Delegate() 之间的区别
【发布时间】:2009-09-02 11:14:29
【问题描述】:
delegate void DelegateTest();

DelegateTest delTest;

调用delTest.Invoke()delTest() 有什么区别?两者都会在当前线程上执行委托,对吧?

【问题讨论】:

    标签: c# delegates


    【解决方案1】:

    delTest() 表单是一个编译器助手,在它下面实际上是对Invoke() 的调用。

    【讨论】:

    • @Richard:Invoke() 在内部做了什么。这个 Invoke 方法到底在哪里。我在 Delegate 和 MultiCastDelegate 的元数据文件中没有找到。
    • @Jose:它们是 CLR 内部实现的一部分,可能被 JIT 编译器直接理解。
    • @Richard:感谢您的回复。后来我遇到了在 SO 中发布的类似问题。还有一个问题,委托的 DynamicInvoke 是做什么的?我在一些论坛上阅读,他们谈到了后期绑定。我不明白它的用法。
    • @Jose:当使用反射动态执行方法时,它相当于 MethodInfo.Invoke 的委托:以obbject[] 传递参数并返回object
    • 我的老教授将其称为“语法糖”。
    【解决方案2】:

    Richard 的回答是正确的,但是从 C# 6.0 开始,由于添加了 null conditional operator,在一种情况下直接使用 Invoke() 可能是有利的。根据 MS 文档:

    空条件成员访问的另一个用途是以线程安全的方式调用委托,代码少得多。旧方式需要如下代码:

    var handler = this.PropertyChanged;
    if (handler != null)  
        handler(…);
    

    新方法要简单得多:

    PropertyChanged?.Invoke(…)   
    

    新方法是线程安全的,因为编译器生成的代码只计算一次 PropertyChanged,将结果保存在一个临时变量中。您需要显式调用 Invoke 方法,因为没有空条件委托调用语法 PropertyChanged?(e)。

    【讨论】:

      【解决方案3】:

      没错。两者的结果完全相同。

      当然,鉴于您已正确初始化 delTest

      【讨论】:

      • 如果 delTestnull,这两种语法再次导致相同的结果(在这种情况下,NullReferenceException 从尝试调用的行抛出)。
      【解决方案4】:

      Delegate.Invoke 和 Delegate() 是相同的。两者都做同样的事情 .见下面代码

      static async Task Main(string[] args)
      {
         MyDelegate mydelegate = new MyDelegate(CallMe);
         mydelegate.Invoke("Reza");
         mydelegate("Reza");
      }
      
      public delegate void MyDelegate(string message);
      public static void CallMe(string message)
      {
      }
      
      

      IL

      IL_001a: ldarg.0
      IL_001b: ldfld class TestConsole.Program/MyDelegate TestConsole.Program/'<Main>d__1'::'<mydelegate>5__1'
      IL_0020: ldstr "Reza"
      IL_0025: callvirt instance void TestConsole.Program/MyDelegate::Invoke(string)
      IL_002a: nop
      IL_002b: ldarg.0
      IL_002c: ldfld class TestConsole.Program/MyDelegate TestConsole.Program/'<Main>d__1'::'<mydelegate>5__1'
      IL_0031: ldstr "Reza"
      IL_0036: callvirt instance void TestConsole.Program/MyDelegate::Invoke(string)
      IL_003b: nop
      

      我通常使用Invoke(),因为您可以使用 null-check,并且阅读代码的人可以更轻松地看到正在使用委托。

      空检查

      MyDelegate mydelegate = null;
      mydelegate?.Invoke("Reza");
      mydelegate("Reza"); // Error: System.NullReferenceException
      

      【讨论】:

        猜你喜欢
        • 2014-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-25
        • 2020-05-10
        相关资源
        最近更新 更多