Почему кто-то должен быть подписан на событие для появления?

Вы могли бы рассмотреть возможность вызова querySelector независимо, а затем проверить, был ли выбран элемент, вместо того, чтобы иметь различные блоки if (row > 0) ... ранее. Например:

tryChange(-1, 0);
tryChange(1, 0);
tryChange(0, -1);
tryChange(0, 1);
function tryChange(xDiff, yDiff) {
  const sel = "td[data-row='"+(row + xDiff)+"'][data-col='"+(col + yDiff)+"']";
  const elem = document.querySelector(sel);
  if (elem) {
    elem.classList.toggle('yellow');
  }
}

Тест if (elem) не пройден, если ни один элемент не был выбран.

12
задан xyz 16 October 2008 в 17:03
поделиться

9 ответов

Необходимо понять то, что на самом деле делает объявление события. Это объявляет и событие и переменную, Когда Вы обращаетесь к нему в классе, Вы просто обращаетесь к переменной, которая будет пустой, когда не будет никаких подписчиков.

3
ответ дан 2 December 2019 в 06:10
поделиться

Очень Дзэн, а?

Необходимо протестировать на пустой указатель, когда Вы хотите сгенерировать событие:

protected void OnMyEvent()
{
    if (this.MyEvent != null) this.MyEvent(this, EventArgs.Empty);
}

Было бы хорошо, если бы Вы не должны были беспокоиться этим, но them's повреждения.

3
ответ дан 2 December 2019 в 06:10
поделиться

Ну, каноническая форма:

void OnMadeSound()
{
    if (MadeSound != null)
    {
        MadeSound(this, new EventArgs());
    }
}

public void Fall() {  OnMadeSound(); }

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

6
ответ дан 2 December 2019 в 06:10
поделиться

James обеспечил хорошее техническое обоснование, я также хотел бы добавить, что я видел, что люди используют это преимущество, если никакие подписчики не будут слушать событие, то они примут меры для входа его в коде или чем-то подобном. simpl пример, но помещающийся в этот контекст.

2
ответ дан 2 December 2019 в 06:10
поделиться

Иначе я видел для обхождения этого, не имея необходимость не забывать проверять на пустой указатель:

class Tree
{
    public event EventHandler MadeSound = delegate {};

    public void Fall() { MadeSound(this, new EventArgs()); }

    static void Main(string[] args)
    {
        Tree oaky = new Tree();
        oaky.Fall();
    }
}

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

4
ответ дан 2 December 2019 в 06:10
поделиться

Рекомендуемый шаблон (.net 2.0 +)

public class MyClass
{
    public event EventHandler<EventArgs> MyEvent; // the event

    // protected to allow subclasses to override what happens when event raised.
    protected virtual void OnMyEvent(object sender, EventArgs e)
    {
        // prevent race condition by copying reference locally
        EventHandler<EventArgs> localHandler = MyEvent;
        if (localHandler != null)
        {
            localHandler(sender, e);
        }
    }
    public void SomethingThatGeneratesEvent()
    {
        OnMyEvent(this, EventArgs.Empty);
    }
}

Я вижу много рекомендаций для пустого делегата {} в инициализаторе, но я полностью не соглашаюсь с ним. Если Вы следуете за вышеупомянутым шаблоном, Вы только проверяете event != null в одном месте. Пустой делегат {} инициализатор является отходами, потому что это - дополнительный вызов на событие, это тратит впустую память, и это все еще может перестать работать, если MyEvent был установлен в NULL в другом месте в моем классе.

*, Если бы Ваш класс изолируется, Вы не сделали бы OnMyEvent() виртуальный.

4
ответ дан 2 December 2019 в 06:10
поделиться

Какой смысл того, чтобы генерировать событие, если никто не слушает? Технически, его, как C# принял решение реализовать его.

В C# событие является делегатом с некоторыми специальными растушевками. Делегат в этом случае может быть просмотрен как связанный список указателей функции (к методам обработчиков подписчиков). Когда Вы 'стреляете, событие' каждый указатель функции вызывается в свою очередь. Первоначально делегат является несуществующим объектом как что-либо еще. Когда Вы делаете + = для первого, подписывают действие, Делегата. Объединение называют, который инстанцирует списка. (Вызов пустого указателя. Вызовите (), бросает пустую исключительную ситуацию - когда событие запущено.)

Если Вы все еще чувствуете, что "это не должно быть", использует класс помощника EventsHelper, как упомянуто здесь со старым и улучшенным 'защитным событием, публикующим' http://weblogs.asp.net/rosherove/articles/DefensiveEventPublishing.aspx

2
ответ дан 2 December 2019 в 06:10
поделиться

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

Gishu заявил

Какой смысл того, чтобы генерировать событие, если никто не слушает?

Ну, возможно, это - вещь терминологии. Обращение системы "события" кажется мне, что вся ответственность осадков события, которое произошло, должна быть на наблюдателях а не исполнителе.


Возможно, лучшая вещь спросить: Если поле делегата объявляется с ключевым словом события перед ним, почему не делает компилятора, переводят все экземпляры:

MadeSound(this, EventArgs.Empty)

кому:

if (MadeSound != null) { MadeSound(this, EventArgs.Empty); }

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

0
ответ дан 2 December 2019 в 06:10
поделиться

В этом случае было бы полезно использовать метод расширения.

public static class EventExtension
{
    public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs
    {
        if (handler != null)
        {
            handler(obj, args);
        }
    }
}

Затем его можно использовать, как показано ниже.

public event EventHandler<YourEventArgs> YourEvent;
...
YourEvent.RaiseEvent(this, new YourEventArgs());
1
ответ дан 2 December 2019 в 06:10
поделиться
Другие вопросы по тегам:

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