очень простое размышление делегата - PullRequest
1 голос
/ 25 апреля 2010

Иногда самые простые вопросы заставляют меня любить 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 t = SomeMethod; это просто ярлык для TestDelgate t = new TestDelgate (SomeMethod); или есть другая причина для существования метода 2

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

Ответы [ 7 ]

4 голосов
/ 26 апреля 2010

Да, метод 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);

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

2 голосов
/ 26 апреля 2010

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

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

Этот синтаксис также поддерживается для событий .

1 голос
/ 26 апреля 2010

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

 someObj.Test -= new TestDelegate(SomeMethod);

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

 RemoveHandler someObj.Test, AddressOf SomeMethod


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

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

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

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

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

1 голос
/ 26 апреля 2010
  1. Да, они составлены в одно и то же.

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

0 голосов
/ 20 декабря 2010

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

0 голосов
/ 26 апреля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...