Исключение NullReferenceException при запуске события
Рассмотрим следующее:
class Client
{
public static event EventHandler connectFailed;
private Socket socket;
public Client()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endpoint = new IPEndpoint(
IPAddress.Parse("192.168.1.100"),
7900
);
try
{
socket.Connect(endpoint);
}
catch(Exception e)
{
connectFailed(e, new EventArgs());
}
}
}
Предположим, что остальная часть кода реализована (обработчики событий и т.д. в Program.cs).
Я столкнулся с проблемой с NullRefrerenceException
в строке connectFailed(e, new EventArgs());
, и я не могу понять, почему. Все мои другие события увольняются очень хорошо, и я не понимаю, как это все по-другому.
Любые идеи?
Ответы
Ответ 1
Вам нужна нулевая проверка С#, вы не можете вызывать события, когда в этом событии нет обработчиков.
Нормальным было бы реализовать метод OnConnectFailed:
protected virtual void OnConnectFailed(e as EventArgs) {
EventHandler tmp = connectFailed;
if(tmp != null)
tmp(this,e);
}
Кроме того, первым аргументом обработчика события должен быть this
, а не исключение. Если вам нужно передать исключение в обработчик событий, создайте класс EventArgs
со свойством исключения.
Кроме того, нет смысла в создании события из конструктора... ничто не может добавить к нему обработчик.
Ответ 2
Нашел,
public delegate void OnRequestReceivedHandler(object sender);
public event OnRequestReceivedHandler ReqeustReceived = delegate { };
Ответ 3
Также в С# 6 вы можете выполнить нулевую проверку следующим образом:
connectFailed?.Invoke(this, e);
Ответ 4
'connectFailed' - это событие.
Если никто не подозревает о событии, он будет пустым, поэтому вам нужно проверить нулевой случай.
Чтобы сделать это безопасным, вам понадобится нулевая проверка, например:
if (connectFailed != null)
connectFailed(e, new EventArgs());
Однако, этого шаблона недостаточно, из-за многопоточности. Рекомендуемый подход:
EventHandler temp = connectFailed;
if (temp != null)
temp(e, new EventArgs());
Это не только проверяет нулевое условие, но и сначала копирует событие, чтобы гарантировать его потокобезопасность (если очередь событий изменяется одним потоком, в то время как событие обрабатывается в другом потоке, поведение может быть undefined. Сначала скопировав его, вы убедитесь, что список подписчиков остается неизменным в течение всего процесса обработки событий)