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

Это - вопрос об эффективности. LinkedList является быстрым для добавления и удаления элементов, но медленным для доступа к определенному элементу. ArrayList быстро для доступа к определенному элементу, но может не спешить добавлять к любому концу, и особенно медленный для удаления в середине.

Массив по сравнению с ArrayList по сравнению с LinkedList по сравнению с Вектором идет больше подробно, как делает Связанный список .

34
задан peterh says reinstate Monica 12 November 2017 в 00:58
поделиться

4 ответа

На самом деле событие - это просто операция «добавить» и «удалить». Вы не можете получить значение, вы не можете установить значение, вы не можете его вызвать - вы можете просто подписать обработчик для события ( 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 ], чтобы вернуться независимо от того, есть они или нет. Однако это не часть основной модели событий.

58
ответ дан 27 November 2019 в 16:24
поделиться

Здесь немного другой вопрос

Какое значение имеет тестирование внешне определенного события на ноль?

Как внешний потребитель события вы можете выполнять только 2 операции

  • Добавить обработчик
  • Удалить обработчик

Нулевое или ненулевое значение события не имеет отношения к этим двум действиям. Почему вы хотите запустить тест, который не дает ощутимой ценности?

2
ответ дан 27 November 2019 в 16:24
поделиться

Это правило применяется при использовании ключевого слова «событие». Когда вы создаете событие, вы ограничиваете взаимодействие внешнего класса с делегатом отношением «подписаться / отказаться от подписки», включая случаи наследования. Помните, что событие по сути является свойством, но для вызовов методов оно не является самим объектом, поэтому на самом деле оно выглядит примерно так:

public event SomeEventHandler SomeEvent
{
     add
     {
          //Add method call to delegate
     }
     remove
     {
          //Remove method call to delegate
     }
}
1
ответ дан 27 November 2019 в 16:24
поделиться

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

protected void OnSomeEvent(EventArgs e) {
    // CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.
    if (SomeEvent != null) SomeEvent(this, e);
}

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

0
ответ дан 27 November 2019 в 16:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: