Подтвердить что ты не робот

Действие <T> против делегирования

Я видел разработчиков, использующих приведенные ниже коды, в качестве альтернативы. Какая разница между ними и какие из них идут по стандарту? Являются ли они такими же, как Action и Func<T> также является делегатом:

public event Action<EmployeeEventAgs> OnLeave;
public void Leave()
{
    OnLeave(new EmployeeEventAgs(this.ID));
}

VS

public delegate void GoOnLeave(EmployeeEventAgs e);
public event GoOnLeave OnLeave;
public void Leave()
{
    OnLeave(new EmployeeEventAgs(this.ID));
}
4b9b3361

Ответ 1

Fwiw, ни один пример не использует стандартные соглашения .NET. Генератор EventHandler<T> должен объявить событие:

public event EventHandler<EmployeeEventArgs> Leave;

Префикс "On" должен быть зарезервирован для защищенного метода, который вызывает событие:

protected virtual void OnLeave(EmployeeEventArgs e) {
    var handler = Leave;
    if (handler != null) handler(this, e);
}

Вам не обязательно это делать, но кто-то мгновенно распознает шаблон, понимает ваш код и знает, как его использовать и настраивать.

И это имеет большое преимущество в том, что вы не должны выбирать между пользовательским объявлением делегата и Action<>, EventHandler<> - лучший способ. Что отвечает на ваш вопрос.

Ответ 2

Action<T> точно такой же, как delegate void ... (T t)

Func<T> точно совпадает с delegate T ... ()

Ответ 3

Следующие две строки кода почти эквивалентны:

public event Action<EmployeeEventAgs> Leave;

в отличие от:

public event EventHandler<EmployeeEventAgs> Leave;

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

public void LeaveHandler(EmployeeEventAgs e) { ... }

а затем это:

obj.Leave += LeaveHandler;

При втором подходе подпись LeaveHandler должна быть другой:

public void LeaveHandler(object sender, EmployeeEventAgs e) { ... }

Очень важно заметить, что в обоих случаях присутствует ключевое слово event. Событие, объявленное явно как таковое с помощью ключевого слова event, больше не является полем класса. Вместо этого он становится событием. Свойства события аналогичны регулярным свойствам, за исключением того, что у них нет аксессуаров get или set. Компилятор позволяет использовать их только в левой части назначений += и -= (добавление или удаление обработчика событий). Невозможно перезаписать уже назначенные обработчики событий или вызвать событие вне класса, объявляющего его.

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

obj.Leave = LeaveHandler;

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

Кроме того, вы также можете выполнить этот вызов:

obj.Leave(new EmployeeEventAgs());

Два примера выше рассматриваются как анти-шаблон, если вы собираетесь создать событие. Событие должно быть вызвано только объектом-владельцем и не должно допускать бесстрастного удаления подписчиков. Ключевое слово event - это программная конструкция .NET, которая помогает вам правильно использовать события.

Учитывая вышеизложенное, я считаю, что многие придерживаются подхода EventHandler, потому что вряд ли он использует EventHandler без ключевого слова event. Действия имеют более широкий спектр использования, они не выглядят естественно при использовании в качестве событий. Последнее, конечно, личное мнение, так как подход обработчика событий, вероятно, слишком сильно изменился в моих методах кодирования. Тем не менее, если действия используются правильно, это не преступление, чтобы использовать их для событий.

Ответ 4

Действие - это всего лишь ярлык для полного объявления делегата.

public delegate void Action<T>(T obj)

http://msdn.microsoft.com/en-us/library/018hxwa8.aspx

Какой из них будет зависеть от стандартов/стиля кодирования вашей организации.

Ответ 5

Да, Action и Func - это просто удобные делегаты, которые были определены в 3.5 clr.

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

В них нет ничего волшебного. Несколько человек написали простые 2.0 аддон-библиотеки, чтобы добавить эту функциональность в код 2.0.

Ответ 6

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

Ответ 7

В общем, они эквивалентны. Но в контексте использования делегата для типа события соглашение должно использовать EventHandler (где T наследует EventArgs):

public event EventHandler<EmployeeEventArgs> Left;

public void Leave()
{
    OnLeft(this.ID);
}

protected virtual void OnLeft(int id)
{
    if (Left != null) {
        Left(new EmployeeEventArgs(id));
    }
}

Ответ 8

Вы могли бы написать эти общие делегаты Action и Func самостоятельно, но поскольку они в целом полезны, они написали их для вас и застряли в библиотеках .Net.