Вы могли бы рассмотреть возможность вызова 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)
не пройден, если ни один элемент не был выбран.
Необходимо понять то, что на самом деле делает объявление события. Это объявляет и событие и переменную, Когда Вы обращаетесь к нему в классе, Вы просто обращаетесь к переменной, которая будет пустой, когда не будет никаких подписчиков.
Очень Дзэн, а?
Необходимо протестировать на пустой указатель, когда Вы хотите сгенерировать событие:
protected void OnMyEvent()
{
if (this.MyEvent != null) this.MyEvent(this, EventArgs.Empty);
}
Было бы хорошо, если бы Вы не должны были беспокоиться этим, но them's повреждения.
Ну, каноническая форма:
void OnMadeSound()
{
if (MadeSound != null)
{
MadeSound(this, new EventArgs());
}
}
public void Fall() { OnMadeSound(); }
который очень немного быстрее, что вызов пустого делегата, таким образом, скорость добилась успеха по программированию удобства.
James обеспечил хорошее техническое обоснование, я также хотел бы добавить, что я видел, что люди используют это преимущество, если никакие подписчики не будут слушать событие, то они примут меры для входа его в коде или чем-то подобном. simpl пример, но помещающийся в этот контекст.
Иначе я видел для обхождения этого, не имея необходимость не забывать проверять на пустой указатель:
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();
}
}
Отметьте анонимного делегата - вероятно, небольшой хит производительности, таким образом, необходимо выяснить, какой метод (проверяют на пустой указатель или пустого делегата), работы лучше всего в ситуации.
Рекомендуемый шаблон (.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()
виртуальный.
Какой смысл того, чтобы генерировать событие, если никто не слушает? Технически, его, как C# принял решение реализовать его.
В C# событие является делегатом с некоторыми специальными растушевками. Делегат в этом случае может быть просмотрен как связанный список указателей функции (к методам обработчиков подписчиков). Когда Вы 'стреляете, событие' каждый указатель функции вызывается в свою очередь. Первоначально делегат является несуществующим объектом как что-либо еще. Когда Вы делаете + = для первого, подписывают действие, Делегата. Объединение называют, который инстанцирует списка. (Вызов пустого указателя. Вызовите (), бросает пустую исключительную ситуацию - когда событие запущено.)
Если Вы все еще чувствуете, что "это не должно быть", использует класс помощника EventsHelper, как упомянуто здесь со старым и улучшенным 'защитным событием, публикующим' http://weblogs.asp.net/rosherove/articles/DefensiveEventPublishing.aspx
Спасибо за ответы. Я действительно понимаю, почему NullReferenceException происходит и как обойти его.
Gishu заявил
Какой смысл того, чтобы генерировать событие, если никто не слушает?
Ну, возможно, это - вещь терминологии. Обращение системы "события" кажется мне, что вся ответственность осадков события, которое произошло, должна быть на наблюдателях а не исполнителе.
Возможно, лучшая вещь спросить: Если поле делегата объявляется с ключевым словом события перед ним, почему не делает компилятора, переводят все экземпляры:
MadeSound(this, EventArgs.Empty)
кому:
if (MadeSound != null) { MadeSound(this, EventArgs.Empty); }
негласно таким же образом то, что другие ярлыки синтаксиса? Количество шаблона пустой указатель OnSomeEvent проверка методов, которые люди должны записать вручную, должно быть колоссальным.
В этом случае было бы полезно использовать метод расширения.
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());