NullReferenceException при инициировании события - PullRequest
19 голосов
/ 24 апреля 2011

Рассмотрим следующее:

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());, и я не могу понять, почему. Все мои другие события проходят просто отлично, и я не вижу, как это отличается.

Есть идеи?

Ответы [ 4 ]

29 голосов
/ 24 апреля 2011

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

Нормально было бы реализовать метод OnConnectFailed:

protected virtual void OnConnectFailed(e as EventArgs) {
    EventHandler tmp = connectFailed;
    if(tmp != null)
        tmp(this,e);
}

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

Также нет смысла вызывать событие из конструктора ... ничто не может добавитьобработчик к нему.

8 голосов
/ 08 декабря 2015

Также в C # 6 вы можете выполнить проверку нуля следующим образом:

connectFailed?.Invoke(this, e); 
7 голосов
/ 17 декабря 2013

Нашел,

public delegate void OnRequestReceivedHandler(object sender);
public event OnRequestReceivedHandler ReqeustReceived = delegate { };
1 голос
/ 24 апреля 2011

'connectFailed' - это событие.Если никто не подписывается на событие, оно будет нулевым, поэтому вы должны проверить нулевой регистр.

Чтобы сделать это безопасным, вам понадобится нулевая проверка, то есть:

if (connectFailed != null)
    connectFailed(e, new EventArgs()); 

Однако , этого шаблона недостаточно из-за многопоточности.Рекомендуемый подход такой:

EventHandler temp = connectFailed;
if (temp != null)
    temp(e, new EventArgs()); 

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

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