我知道dispose pattern,并希望正确处置我的Socket资源。他们在文档中建议使用SafeHandles,但是我不确定System.Net.Socket的工作原理。我发现Socket类本身包含一个SafeSocketHandle,但我不知道如何使用它。我是否需要布置手柄和插座,或者仅布置手柄就足够了吗?我假设在该类中,我仅使用套接字操作的句柄,对吧?
public class MySocket : IDisposable
{
private SafeSocketHandle _handle;
private bool _disposed = false;
public MySocket(AddressFamily addressFamily)
{
Socket s = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
_handle = s.SafeHandle;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_handle.Dispose();
}
_disposed = true;
}
}
[也许有人也能够解释为什么应该使用SafeHandles?我是说这还不够吗?:
public class MySocket : IDisposable
{
private Socket _socket;
private bool _disposed = false;
public MySocket(AddressFamily addressFamily)
{
_socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_socket.Dispose();
}
_disposed = true;
}
}
[当您直接管理非托管资源时,应使用SafeHandle
。
使用Socket
,存在底层的非托管资源,但这由Socket
类处理。您无需参与其中-Socket
本身是托管资源,而不是非托管资源。 Socket
有自己的终结器,如果您忘记处理它,它将释放底层的非托管资源。
所以,这里您不必担心SafeHandles
。只需实现IDisposable
并调用_socket.Dispose()
。
您不需要需要在此处实现完整的Dispose模式,除非您可能拥有一个拥有自己非托管资源的派生类。编写就足够了:
public class MySocket : IDisposable
{
private Socket _socket;
private bool _disposed = false;
public MySocket(AddressFamily addressFamily)
{
_socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
}
public void Dispose()
{
_socket.Dispose();
_disposed = true;
}
}
实际上,许多编码标准要求将非托管资源必须包装在SafeHandle
中。如果执行此操作,则无需实现完整的Dispose模式。
如果您do需要实现完整的处置模式,则还需要编写一个终结器。您问题中的代码无法执行此操作。
实际上,处置模式鼓励用户走上一条相当危险的道路-用void Dispose(bool disposing)
方法编写正确的代码确实非常困难,并且存在大多数用户不知道的陷阱。这就是.NET 2.0中引入SafeHandle
的原因-运行时对此有特殊的支持,避免了这些陷阱-但有关IDisposable
的建议似乎从未更新过。