2009-04-22 2 views
33

Если вам нравится создавать пользовательские делегаты, вы должны использовать ключевое слово delegate в нижнем регистре.Ключевое слово Delegate vs. delegate

Что вы можете сделать с фактическим классом делегата? Для чего это полезно? Не понимаю точной разницы.

ответ

34

От http://msdn.microsoft.com/en-us/library/system.delegate.aspx:

Delegate класс является базовым классом для типов делегатов. Однако только система и составители могут получить явно из класса Delegate или из класса MulticastDelegate. Это также недопустимо для получения нового типа из типа делегата. Класс Delegate не считается тип делегата; это класс, используемый для для получения типов делегатов.

Большинство языков реализуют delegate ключевого слова, и компиляторы для этих языков способны вывести из класса MulticastDelegate; поэтому пользователи должны использовать ключевое слово delegate , предоставляемое языком.

+1

Хорошая выборка из MSDN;) – Xian

+0

http://msdn.microsoft.com/en-us/library/system.delegate.aspx – Xian

2

Преимущество класса Delegate заключается в том, что он является базовым классом для всех типов делегатов в .NET. Наличие метода, который принимает экземпляр этого класса, позволяет вам работать в целом по всем типам делегатов. Вот почему такие операции, как ISynchronizedInvoke.Invoke, используют это как параметр.

+4

Следует отметить, однако, что вызов делегата таким образом является поздним и, соответственно, медленным. –

34

Ключевое слово delegate предназначено для компилятора, чтобы сделать для вас магию. Когда вы объявляете нового делегата с пользовательской подписью,

  • компилятор создает новый тип для вас, полученный из MulticastDelegate (который, в свою очередь, происходит от делегата).
  • компилятор добавляет метод Invoke с пользовательской подписи
  • так же компилятор добавляет BeginInvoke и методы EndInvoke для этого нового типа

Итак, теперь, когда вы звоните delObject(args) - компилятор транслирует, что delObject.Invoke(args)

Основной класс делегата предоставляет некоторые функциональные возможности, такие как

  1. CreateDelegate (для получения dele gate wrapping static/instance method)
  2. DynamicInvoke (для вызова делегата со списком аргументов - поздняя привязка)
  3. Объединение и удаление (для делегирования цепочки) объединение нескольких делегатов, например. несколько делегатов обработчика событий для события)

Компилятор C# запрещает вам извлекать из делегата эксплицитно в ваш код .. вам нужно использовать ключевое слово delegate.

+1

+1: Специально говоря, что «компилятор создает новый тип для вас, полученный из MulticastDelegate», , Таким образом, по умолчанию делегаты, которые мы создаем, являются делегатами многоадресной передачи. – A9S6

+0

Ясно. Мне нравится ваш ответ. –

+0

'компилятор создает новый тип для вас, полученный из MulticastDelegate' Я не уверен в этом. Согласно http://msdn.microsoft.com/en-us/library/system.delegate.aspx 'Однако, только система и компиляторы могут получить явно из класса Delegate или из класса MulticastDelegate.« Обратите внимание на ключевое слово " ** или ** " –

1

С точки зрения реализации класс Delegate определяет поля, используемые для представления указателя функции делегата, а класс MultiCastDelegate предоставляет функциональность базовой линии, используемую событиями. Кроме того, как отмечали другие люди, делегат предоставляет метод DynamicInvoke, который позволяет вам вызывать любого делегата.

3

Еще одна полезная вещь, которую вы можете сделать с delegate ключевого слова создают делегатов рядный, без необходимости объявлять их, например:

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

Синтаксис лямбда C# 3.0 гораздо менее подробный. –

2

Одна из вещей 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(); 
     } 
    } 
}