2010-04-25 6 views
1

Иногда самые простые вопросы заставляют меня любить C/C++ и C# все больше и больше.очень простой делегат размышления

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

Например:

public static void SomeMethod(string message) 
    { 
     ... 
    } 

    ... 


    public delegate void TestDelgate(string message); //Define a delegate 

    ........... 

    //create a new instance ..METHOD 1 
    TestDelgate t = new TestDelgate(SomeMethod); 

    //OR another way to create a new instance ..METHOD 2 
    TestDelgate t = SomeMethod; //create a new instance ..METHOD 2 

Так сегодняшние вопросы являются

  1. Что происходит под капотом в методе 2. расширить ли компилятор метод 2 в способе 1, поэтому писать TestDelgate т = SomeMethod ; это просто ярлык для TestDelgate т = новый TestDelgate (SomeMethod) ;, или есть другая причина для exsitence метода 2

  2. ли вы, ребята, думаете, метод 1 или метод 2 лучше для удобства чтения (это субъективное вопрос, но я бы хотел, чтобы получить ненаучное ощущение общего мнения StackOverflow :-))

+1

Связанный вопрос: http://stackoverflow.com/questions/550703/c-difference-between-anevent-and-new-eventhandleranevent/550708#550708 – driis

ответ

1

Это сахар. Это тип сахара, который действительно пригодится, когда вам нужно это написать:

someObj.Test -= new TestDelegate(SomeMethod); 

Что? Вы должны использовать новое ключевое слово для удалить обработчик события. Да, да. Команда VB.NET очень больно об этом, они решили на совершенно иной синтаксис:

RemoveHandler someObj.Test, AddressOf SomeMethod 


Даже выше C# оператор является сахар, реальный код выглядит следующим образом:

someObj.Test.remove(new TestDelegate(this, SomeMethod)); 

Где «remove» - это функция доступа для события. И «это» требуется для инициализации свойства Delegate.Target. Теперь очевидно, что на самом деле это вызов метода, и использование нового ключевого слова внезапно имеет смысл. Скрытие «этого» также имеет некоторые недостатки, теперь уже не очевидно, что подписка на события предотвратит сбор объекта из мусора.

1
  1. Да они собраны в одно и то же.

  2. Я предпочитаю # 2. Просто потому, что он короче и не так неуклюж. Вы уже знаете, что это TestDelegate из-за определения этого раньше. Так зачем писать снова?

2

Под капотом ваши 2 метода точно такие же. Компилятор просто соображает, что вы хотите сделать. Эта небольшая функция называется delegate inference и была добавлена ​​в C# 2.0.

Я думаю, вы должны использовать # 2 и воспользоваться делегацией. Они скомпилируются с тем же IL, а опция № 2 короче и более кратким. Легче читать и понимать смысл кода, потому что меньше шума.

Этот синтаксис also supported for events.

0

Под капотом оба оператора создают объект-делегат и передают параметры на ctor: адрес метода и ссылку на него. второй - просто синтаксический сахар.

4

Да, метод 2 является только сокращением для метода 1 - по крайней мере, в случае использования группы методов. Вы можете также использование:

TestDelegate t = new TestDelegate(someExistingDelegate); 

, которая позволяет дисперсии (не только родовое отклонение от C# 4) и создает отдельный делегат ... но это редко бывает полезна.

Лично я перехожу к варианту 2 ... конверсии групп очень удобны. В частности, это делает проводку событие проще:

button.Click += LoadDocument; 

вместо

button.Click += new EventHander(LoadDocument); 

Последний раз имеет дополнительный пуха - бывший имеет лучшую плотность информации.Это также важно, когда вы передаете делегат в качестве аргумента метода. Например, сравните:

observable.Subscribe(new Action<string>(Console.WriteLine)); 

с

observable.Subscribe(Console.WriteLine); 

Если нет какой-либо двусмысленности в отношении того, какой тип делегата вы на самом деле хотите, чтобы преобразовать группу метод, я просто использовать неявное преобразование.

1
  1. Это просто синтаксический сахар для явного создания делегата. Это было introduced в C# 2.0. Возможно, вы заметили, что Visual Studio 2008 по-прежнему генерирует синтаксис старого стиля (метод 1), если вы попросите его создать обработчик событий; Я всегда заменяю его вручную новым синтаксисом.

  2. Обычно я предпочитаю более короткую форму в методе 2. Я использовал метод 1 только один раз: с делегатом, который должен был вызываться из собственного кода и, следовательно, не мог быть собран в мусор. Я хотел быть очень откровенным в создании и назначении.

0

Одним из преимуществ синтаксиса «новый» является то, что он сообщил программисту, что выделяется новый объект; если было бы желательно избежать многократного создания новых идентичных делегатов, можно было бы вывести делегата в поле. Я знаю, что на самом деле одному разрешено использовать один делегат для подписки, а другой - отказаться от подписки, но для меня это неправильно. Хранение в поле, которое делегат использовал для подписки, а затем отказаться от подписки с использованием того же делегата, чувствует себя чище. Еще чище, ИМХО, было бы, если бы акт подписки вернул MethodInvoker, который при вызове отменит подписку (в этом случае «событие» просто будет функцией, которая приняла EventHandler и вернула MethodInvoker), но это а не как .net-события работают.

Смежные вопросы