如果我写
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();
}
根据我的经验,using 语句很少与Socket
类一起使用。大多数情况下,您只会调用Socket.Close
which 将在Socket.Dispose
内部实际调用。
Close
在 .NETDispose
中的类中调用。using 块只是调用Socket
.Dispose
但这并不意味着using 块没有用!
在 .NET 中,using 块本质上只是try/finally的语法糖,在using 语句中实现接口Dispose
的对象上调用where 。正如我在下面说明和解释的那样,存在一些差异。IDisposable
以下代码:
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();
}
}
您不仅获得了免费的空检查,而且还为您的Socket
类实例创建了一个额外的范围。
最终,我建议在这种情况下使用 using 块,因为它确保在抛出异常等情况下Dispose
在类的实例上调用它。Socket
在这种情况下使用 using 块时,我可以想出很多收获,实际上没有什么损失。另一方面,当不使用using 块时,我会想到很多损失。
If you look at the code of Socket in ILSpy or Reflector.NET you will see the following code:
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);
}
}
Essentially calling Dispose()
is redundant. Calling Close()
is enough.