Разница в вызовах через делегатов и события C # - PullRequest
4 голосов
/ 07 июня 2011

В чем разница?

Использование делегата

public delegate void TestDelegate();
public TestDelegate delObj = SomeMethod;

public void SomeMethod()
{
    .....
}

public void Test()
{
    if(delObj != null)
        delObj();
}

Использование события

public delegate void TestDelegate();
public event TestDelegate EdelObj += SomeMethod;

public void SomeMethod()
{
    .....
}

public void Test()
{
    if(EdelObj != null)
        EdelObj();
}

Кажется, что оба работают.Кто-нибудь может объяснить, в чем разница, и какой сценарий мы должны использовать один из вышеперечисленных?

Редактирование Цепочка работает для обоих.Извините, это была ошибка с моей стороны.

Спасибо Nishant

Ответы [ 5 ]

2 голосов
/ 07 июня 2011

Объявление события - это на самом деле просто особый вид свойства, который используется для предоставления делегата.Однако вместо того, чтобы получать и устанавливать методы доступа, создаются и удаляются.Обычно они реализуются автоматически, но при желании вы можете добавить пользовательское поведение:

private MyEventHandler handler;
public event MyEventHandler MyEvent {
    add {
        handler += value;
        Trace.WriteLine("MyEvent handler attached.");
    }
    remove {
        handler -= value;
        Trace.WriteLine("MyEvent handler removed.");
    }
}

Это делает две вещи.Во-первых, поскольку события являются свойствами, они могут быть включены в интерфейсы.Во-вторых, поскольку MyEvent не возвращает значение, делегат полностью инкапсулируется, и только объект, которому он принадлежит, может вызвать его.Другие способы представления делегатов приводят к тому, что делегатом может быть вызван практически любой человек.

Помимо этой особой языковой поддержки, другим важным отличием между событиями и делегатами является соглашение, а не функция языка или структуры.: Ожидается, что события будут следовать определенным шаблонам , например, убедитесь, что делегат, на котором основано событие, следует шаблону, установленному делегатом EventHandler .

Как правило, события предпочтительны, когда семантика - это объект, уведомляющий любого, кто интересуется изменением его стадии.Делегаты предпочтительнее в ситуациях, когда вы хотите, чтобы другие могли определять поведение, предоставляя свою собственную процедуру, такую ​​как параметры делегата, которые принимаются многими методами расширения в IEnumerable, которые используются в LINQ.

2 голосов
/ 07 июня 2011

Работает точно так же.Если вы используете

public event EventHandler SomeEvent;

компилятор C # делает (упрощенный код):

private EventHandler SomeEventField;
public void add_SomeEvent( EventHandler handler) {
    this.SomeEventField = (EventHandler)Delegate.Combine(this.SomeEvent, handler);
}
public void remove_SomeEvent( EventHandler ) {
   this.SomeEventField = (EventHandler)Delegate.Remove(this.SomeEvent, handler);
}

Метод add_SomeEvent вызывается, когда вы используете SomeEvent += ..., а remove_SomeEventпри использовании SomeEvent -= ....

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

1 голос
/ 07 июня 2011

Это фактически оболочка свойства вокруг события.

Основное отличие состоит в том, что вы не можете вызывать / вызывать событие извне класса, тогда как вы можете вызывать открытый делегат.* Цепочка (+ =) не отличается для делегатов и событий.

1 голос
/ 07 июня 2011

Это не делегат против события, событие - это своего рода свойство вокруг делегата.

В общем случае вы всегда должны использовать второй сценарий, потому что в первом public TestDelegate delObj - открытое поле, нарушающее Encapsulation.

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

0 голосов
/ 07 июня 2011

C # имеет много конструкций, которые не добавляют ничего нового в язык, но являются просто синтаксическим сахаром для конструкции, потому что конструкция требует некоторого шаблона кода, который утомительно вводить каждый раз снова и снова. Например, оператор using эквивалентен блоку try-finally с вызовом метода dispose, а свойства являются просто синтаксическим сахаром для метода get и / или set.

Подобным образом события являются просто синтаксическим сахаром для поля делегата. Однако есть некоторые тонкие различия, о которых упоминали другие. Поскольку открытое поле не рекомендуется, делегат должен быть инкапсулирован, и хороший способ сделать это с событием. И (как упоминает Марк) событие вызывается только изнутри класса.

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

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