【问题标题】:Delegate vs. delegate keyword委托与委托关键字
【发布时间】:2009-04-22 20:21:05
【问题描述】:

如果您想创建自定义委托,可以使用小写的 delegate 关键字。

你可以用实际的Delegate 类做什么?这有什么好处?我不明白确切的区别。

【问题讨论】:

    标签: .net delegates


    【解决方案1】:

    来自http://msdn.microsoft.com/en-us/library/system.delegate.aspx

    Delegate 类是基类 对于委托类型。然而,只有 系统和编译器可以导出 明确来自 Delegate 类或 来自MulticastDelegate 类。它 也不允许推导出 委托类型的新类型。这 Delegate 类不被视为 委托类型;它是一个习惯于 派生委托类型。

    大多数语言都实现了delegate 关键字和编译器 语言能够从 MulticastDelegate类;所以, 用户应使用delegate 关键字 由语言提供。

    【讨论】:

      【解决方案2】:

      delegate 关键字是让编译器为你做一些魔术。当您使用自定义签名声明新委托时,

      • 编译器会为您创建一个派生自 MulticastDelegate(又派生自 Delegate)的新类型。
      • 编译器使用您的自定义签名添加 Invoke 方法
      • 类似地,编译器为此新类型添加了 BeginInvoke 和 EndInvoke 方法

      所以现在当您调用 delObject(args) - 编译器会将其转换为 delObject.Invoke(args)

      Delegate 基类提供了一些功能,例如

      1. CreateDelegate(用于获取包装静态/实例方法的委托)
      2. DynamicInvoke(使用参数列表调用委托 - 后期绑定)
      3. 组合和删除(用于委托链接.. 将多个委托链接在一起,例如一个事件的多个事件处理程序委托)

      C# 编译器禁止您在代码中明确地从 Delegate 派生。您必须使用 delegate 关键字。

      【讨论】:

      • +1:特别提到“编译器为你创建了一个从 MulticastDelegate 派生的新类型”。所以默认情况下,我们创建的委托都是多播委托
      • the compiler creates a new Type for you derived from MulticastDelegate 我不确定。根据msdn.microsoft.com/en-us/library/system.delegate.aspxHowever, only the system and compilers can derive explicitly from the Delegate class or from the MulticastDelegate class.请注意关键字“
      【解决方案3】:

      使用 delegate 关键字可以做的另一件事是内联创建委托,而无需声明它们,例如:

      // constructor
      public Form1()
      {
          this.Load += delegate(object sender, EventArgs e)
          {
               // Form1_Load code goes right here
          }
      }
      

      【讨论】:

      • 虽然您提出了一个很好的观点,但是让我们也考虑一下匿名函数适用于 C# 2.0 的事实,建议使用 C# 3.0 中引入的 lambda 表达式而不是匿名函数。参考:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
      • @Explosion 这是 2009 年的答案,今天一切都不同了
      【解决方案4】:

      Delegate 类的优点是它是 .Net 中所有委托类型的基类。拥有一个采用此类实例的方法允许您对所有委托方式进行通用操作。这就是像 ISynchronizedInvoke.Invoke 这样的操作使用 this 作为参数的原因。

      【讨论】:

      • 但是应该注意的是,以这种方式调用委托是后期绑定的并且(相应地)更慢。
      【解决方案5】:

      Delegate 类的用途之一是在调用事件处理程序时进行更多控制。例如,对于正常的事件处理,任何事件处理程序中的异常都会阻止调用任何以后的事件处理程序。您可以通过使用 Delegate 类手动调用每个事件处理程序来更改该行为。

      using System;
      
      namespace DelegateClass
      {
          class EventSource
          {
              public event EventHandler TheEvent;
      
              internal void RaiseEvent1()
              {
                  EventHandler handler = TheEvent;
                  if (handler != null)
                      handler(this, EventArgs.Empty);
              }
      
              internal void RaiseEvent2()
              {
                  EventHandler handler = TheEvent;
                  if (handler == null)
                      return;
      
                  Delegate[] handlers = handler.GetInvocationList();
                  foreach (Delegate d in handlers)
                  {
                      object[] args = new object[] { this, EventArgs.Empty };
                      try
                      {
                          d.DynamicInvoke(args);
                      }
                      catch (Exception ex)
                      {
                          while (ex.InnerException != null)
                              ex = ex.InnerException;
      
                          Console.WriteLine(ex.Message);
                      }
                  }
              }
          }
      
          class Program
          {
              static void Handler1(object sender, EventArgs e)
              {
                  Console.WriteLine("Handler1");
              }
      
              static void Handler2(object sender, EventArgs e)
              {
                  Console.WriteLine("Handler2");
                  throw new InvalidOperationException();
              }
      
              static void Handler3(object sender, EventArgs e)
              {
                  Console.WriteLine("Handler3");
              }
      
              static void Main(string[] args)
              {
                  EventSource source = new EventSource();
                  source.TheEvent += Handler1;
                  source.TheEvent += Handler2;
                  source.TheEvent += Handler3;
      
                  try
                  {
                      source.RaiseEvent1();
                  }
                  catch (Exception ex)
                  {
                      Console.WriteLine(ex.Message);
                  }
      
                  Console.WriteLine("-------------------");
      
                  source.RaiseEvent2();
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        从实现的角度来看,Delegate 类定义了用于表示委托函数指针的字段,而 MultiCastDelegate 类提供了事件使用的基线功能。此外,正如其他人提到的,Delegate 提供了“DynamicInvoke”方法,允许您调用任何委托。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-12
          • 2010-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-17
          相关资源
          最近更新 更多