Есть некий класс. Внутри класса есть делегат и событие
public delegate void stChanged();
public event stChanged StateChanged;
но в том месте, где должно происходить событие, выполнение кода прекращается.
то есть после
StateChanged();
ничего не происходит.
я не знаю как настроить дебугер на отлов всех ошибок, поэтому просто внес строку в блок try{}
И правда, сработало исключение с сообщением: "Ссылка на объект не указывает на экземпляр объекта"
Как понимать такое сообщение при вызове события?
не понял. зачем быть подписанным на событие? У многих классов и компонентов есть события, на которые никто не подписан, которые не обрабатываются программой. Или я чего то не правильно понял? (
в с++ такого не было. Ну да ладно, надо, так надо. Посоветуйте тогда как грамотнее (правильнее) будет делать проверку на подписку? Через try{}? Есть ли более быстрый (с точки зрения времени выполнения) способ?
Через try не нужно проверять, исключения вещь полезная, и в некоторых случаях необходимая, но оборачивать каждую строчку try-ем не стоит, не очень быстро работать будет.
Nipheris: таки да, в с++ были события. По крайней мере если в той же студии создать новый проект на с++, то там будет возможность создавать события. Причем таким же образом, через делегаты. Только на нулл проверять не требуется. Да даже в бейсике есть. Только там вообще не нужно определять никакие делегаты, видимо среда это делает за нас. В общем то это логично, зачем каждый раз писать лишние одинаковые строки? )
Да да, про try я в курсе, просто я не знал как и где мне отловить ошибку, на которую не ругается дебаггер.
MoreBeauty: Ну ваша первая ошибка, это создание своего делегата. А на деле есть Generic делегаты (Action и Func), которые и рекомендуется использовать. Так что берите нормальную книгу и читайте. С Рихтера наверное правда начинать не стоит.
Это тоже не совсем корректный вариант. Правильно так:
var handler = StateChanged;
if (handler != null)
{
handler();
}
Причина - многопоточность. В вашем коде проверка StateChanged != null может вернуть true, а потом перед вызовом события последний обработчик возьмёт да и отпишется из другого потока. Тогда StateChanged уже будет равен null, и вызов приведет к NullReferenceException.
Такой огород - это стандарт, которого нужно придерживаться всегда, независимо от того, пишете ли вы однопоточное или многопоточное приложение. Никогда нельзя знать наверняка, во что эволюционирует ваш код. Кстати, в C# 6.0 эту проблему обещают решить. Благодаря поддержке Null-Conditional Operator-ов, можно будет просто написать: StateChanged?.Invoke();