Это - вопрос об эффективности. LinkedList
является быстрым для добавления и удаления элементов, но медленным для доступа к определенному элементу. ArrayList
быстро для доступа к определенному элементу, но может не спешить добавлять к любому концу, и особенно медленный для удаления в середине.
Массив по сравнению с ArrayList по сравнению с LinkedList по сравнению с Вектором идет больше подробно, как делает Связанный список .
На самом деле событие - это просто операция «добавить» и «удалить». Вы не можете получить значение, вы не можете установить значение, вы не можете его вызвать - вы можете просто подписать обработчик для события ( add
) или отказаться от подписки ( remove
). Это нормально - это инкапсуляция, простая и понятная. Правильно реализовать добавление / удаление зависит от издателя, но если издатель не решит сделать доступными подробности, подписчики не смогут изменять или получать доступ к частям, зависящим от реализации.
События, подобные полям в C # (где вы не указываете биты добавления / удаления) скрыть это - они создают переменную типа делегата и событие. Реализации добавления / удаления события просто используют переменную для отслеживания подписчиков.
Внутри класса вы ссылаетесь на переменную (чтобы вы могли получить подписанных в данный момент делегатов, выполнить их и т. Д.), А вне класса вы ссылаетесь на само событие (чтобы иметь только возможности добавления / удаления).
Альтернатива в события, подобные полям, - это то место, где вы явно реализуете добавление / удаление самостоятельно, например
private EventHandler clickHandler; // Normal private field
public event EventHandler Click
{
add
{
Console.WriteLine("New subscriber");
clickHandler += value;
}
remove
{
Console.WriteLine("Lost a subscriber");
clickHandler -= value;
}
}
См. мою статью о событиях для получения дополнительной информации.
Конечно, публикатор событий может также сделать доступной дополнительную информацию - вы можете написать свойство, например ClickHandlers
, чтобы возвращать текущий многоадресный делегат, или HasClickHandlers
, чтобы возвращать, есть они или нет. Однако это не часть основной модели событий.
Альтернативой полевым событиям является то, где вы явно реализуете добавление / удаление самостоятельно, например
private EventHandler clickHandler; // Normal private field
public event EventHandler Click
{
add
{
Console.WriteLine("New subscriber");
clickHandler += value;
}
remove
{
Console.WriteLine("Lost a subscriber");
clickHandler -= value;
}
}
См. моя статья о событиях для получения дополнительной информации.
Конечно, издатель событий может также предоставить дополнительную информацию - вы можете написать свойство, например ClickHandlers
, чтобы вернуть текущий многоадресный делегат или HasClickHandlers
для возврата независимо от того, есть они или нет. Однако это не часть основной модели событий.
Альтернативой полевым событиям является то, когда вы явно реализуете добавление / удаление самостоятельно, например
private EventHandler clickHandler; // Normal private field
public event EventHandler Click
{
add
{
Console.WriteLine("New subscriber");
clickHandler += value;
}
remove
{
Console.WriteLine("Lost a subscriber");
clickHandler -= value;
}
}
См. моя статья о событиях для получения дополнительной информации.
Конечно, издатель событий может также предоставить дополнительную информацию - вы можете написать свойство, например ClickHandlers
, чтобы вернуть текущий многоадресный делегат или HasClickHandlers
для возврата независимо от того, есть они или нет. Однако это не часть основной модели событий.
Конечно, публикатор события может также предоставить дополнительную информацию - вы можете написать свойство, например ClickHandlers
, чтобы возвращать текущий многоадресный делегат, или HasClickHandlers
], чтобы вернуться независимо от того, есть они или нет. Однако это не часть основной модели событий.
Конечно, публикатор события может также предоставить дополнительную информацию - вы можете написать свойство, например ClickHandlers
, чтобы возвращать текущий многоадресный делегат, или HasClickHandlers
], чтобы вернуться независимо от того, есть они или нет. Однако это не часть основной модели событий.
Здесь немного другой вопрос
Какое значение имеет тестирование внешне определенного события на ноль?
Как внешний потребитель события вы можете выполнять только 2 операции
Нулевое или ненулевое значение события не имеет отношения к этим двум действиям. Почему вы хотите запустить тест, который не дает ощутимой ценности?
Это правило применяется при использовании ключевого слова «событие». Когда вы создаете событие, вы ограничиваете взаимодействие внешнего класса с делегатом отношением «подписаться / отказаться от подписки», включая случаи наследования. Помните, что событие по сути является свойством, но для вызовов методов оно не является самим объектом, поэтому на самом деле оно выглядит примерно так:
public event SomeEventHandler SomeEvent
{
add
{
//Add method call to delegate
}
remove
{
//Remove method call to delegate
}
}
Вам придется делать это из базового класса. Это точная причина, по которой вы сделали это:
protected void OnSomeEvent(EventArgs e) {
// CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.
if (SomeEvent != null) SomeEvent(this, e);
}
Вы не можете получить доступ к событиям из производного класса. Кроме того, вы должны сделать этот метод виртуальным, чтобы его можно было переопределить в производном классе.