使用带有套接字的块

本文关键字:套接字 | 更新日期: 2023-09-27 18:35:36

如果我写

using (Socket s = new Socket(/*...*/))
{
    //...
}

是否调用结束大括号

s.Shutdown(SocketShutdown.Both);
s.Close();
s.Dispose();

或仅

s.Dispose();

(还是别的什么?

谢谢!

使用带有套接字的块

using 语句将调用IDisposable.Dispose,仅此而已。

using 语句只是一个编译器技巧,它允许您更简洁地表达您总是希望处理给定对象,即使块包含的代码抛出并大致转换为以下内容

Socket s = new Socket(...)
try
{
   // Code contained by the using... block here. 
}
finally
{
   s.Dispose();
}

根据我的经验,use 语句很少与 Socket 类结合使用。大多数情况下,您只会调用实际上将在内部调用Socket.DisposeSocket.Close

Close调用 .NET 中Socket类中的Dispose使用块只是调用Dispose

但这并不意味着使用块是无用的!

在 .NET 中,使用块本质上只是 try/finally 的语法糖,其中在 using 语句中实现IDisposable接口的对象上调用Dispose。下面我将说明和解释,存在一些差异。

以下代码:

using (var socket = new Socket(/*...*/))
{
    // operations
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();
}

在编译时展开为以下代码:

{
  Socket socket = new Socket(/*...*/);
  try
  {
      // operations
      socket.Shutdown(SocketShutdown.Both);
      socket.Close();
  }
  finally
  {
    if (socket != null)
      ((IDisposable)socket).Dispose();
  }
}

您不仅可以获得免费的 null 检查,还可以为类Socket实例创建额外的作用域。

最终,我建议在这种情况下使用 using 块,因为它可确保在引发异常等情况下在 Socket 类的实例上调用 Dispose

在这种情况下,当使用使用块时,我可以想到很多收获,而实际上没有什么可失去的。另一方面,我可以想到不使用使用块时会损失很多。

如果你在ILSpy或 Reflector.NET 中查看Socket的代码,你会看到以下代码:

public void Close()
{
    if (Socket.s_LoggingEnabled)
    {
        Logging.Enter(Logging.Sockets, this, "Close", null);
    }
    ((IDisposable)this).Dispose();
    if (Socket.s_LoggingEnabled)
    {
        Logging.Exit(Logging.Sockets, this, "Close", null);
    } 
}

本质上,调用Dispose()是多余的。打电话给Close()就足够了。