请考虑以下事项:
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());
的问题,我无法理解原因。我所有的其他事件都很好,但我不知道这有什么不同。
有什么想法吗?
答案 0 :(得分:29)
您需要进行空检查 - 在C#中,如果没有在该事件上注册处理程序,则无法调用事件。
通常的做法是实现OnConnectFailed方法:
protected virtual void OnConnectFailed(e as EventArgs) {
EventHandler tmp = connectFailed;
if(tmp != null)
tmp(this,e);
}
此外,事件处理程序的第一个参数应该是this
,而不是例外。如果需要将异常传递给事件处理程序,请创建一个带有异常属性的EventArgs
类。
此外,从构造函数中引发事件毫无意义......没有机会为其添加处理程序。
答案 1 :(得分:8)
同样在C#6中,你可以用这种方式进行 null检查:
connectFailed?.Invoke(this, e);
答案 2 :(得分:7)
找到它,
public delegate void OnRequestReceivedHandler(object sender);
public event OnRequestReceivedHandler ReqeustReceived = delegate { };
答案 3 :(得分:1)
'connectFailed'是一个事件。 如果没有人怀疑该事件,它将为null,因此您必须检查空案例。
为了确保安全,您需要进行空检查,即:
if (connectFailed != null)
connectFailed(e, new EventArgs());
然而,由于多线程,这种模式还不够。推荐的方法是:
EventHandler temp = connectFailed;
if (temp != null)
temp(e, new EventArgs());
这不仅会检查null条件,还会先复制事件以确保它是线程安全的(如果在另一个线程上处理事件时事件队列被一个线程更改,则行为可能是未定义的通过先复制它,确保用户列表在事件处理过程中保持不变)