Предыдущие комментарии об использовании абстрактных классов для общей реализации, безусловно, находятся на грани. Одно из преимуществ, о которых я еще не упоминал, заключается в том, что использование интерфейсов значительно упрощает реализацию макетных объектов для модульного тестирования. Определение IPet и PetBase, как описано Джейсоном Коэном, позволяет легко обманывать различные условия данных без накладных расходов на физическую базу данных (пока вы не решите, что пришло время проверить реальную вещь).
Я описал это в изрядном количестве детали в статья , но вот сводка, предполагая, что Вы довольно довольны делегаты сами:
Для подобных полю событий, существует некоторая синхронизация, но иначе добавление/удаление просто звонит Делегату. Объединение / Удаляют для изменения значения автоматически сгенерированного поля. Обе из этих операций присваивают отступающему полю - помнят, что делегаты неизменны. Другими словами, автоматически сгенерированный код очень похож на это:
// Backing field
// The underscores just make it simpler to see what's going on here.
// In the rest of your source code for this class, if you refer to
// ElementAddedEvent, you're really referring to this field.
private EventHandler<EventArgs> __ElementAddedEvent;
// Actual event
public EventHandler<EventArgs> ElementAddedEvent
{
add
{
lock(this)
{
// Equivalent to __ElementAddedEvent += value;
__ElementAddedEvent = Delegate.Combine(__ElementAddedEvent, value);
}
}
remove
{
lock(this)
{
// Equivalent to __ElementAddedEvent -= value;
__ElementAddedEvent = Delegate.Remove(__ElementAddedEvent, value);
}
}
}
начальное значение сгенерированного поля в Вашем случае null
- и это будет всегда становиться null
снова, если все подписчики будут удалены, поскольку это - поведение Делегата. Удалить.
, Если Вы хотите, чтобы обработчик "нет" подписался на Ваше событие, чтобы избежать проверки ничтожности, можно сделать:
public EventHandler<EventArgs> ElementAddedEvent = delegate {};
Эти delegate {}
просто анонимный метод, который не заботится о его параметрах и ничего не делает.
, Если существует что-нибудь, которое это все еще неясно, спросите, и я попытаюсь помочь!
Под капотом события являются просто делегатами со специальными соглашениями о вызовах. (Например, Вы не должны проверять на ничтожность прежде, чем сгенерировать событие.)
В псевдокоде, Событии. Вызовите (), ломается как это:
, Если Событие Сделало, чтобы Слушатели Позвонили каждому слушателю синхронно на этом потоке в произвольном порядке.
события Since многоадресно передаются, у них будут нуль или больше слушателей, сохраненных в наборе. CLR циклично выполнится через них, называя каждого в произвольном порядке.
Один большой протест помнить состоит в том, что обработчики событий выполняются в том же потоке, как событие генерируется в. Это - общая умственная ошибка думать о них как о порождении нового потока. Они не делают.