If I write
using (Socket s = new Socket(/*...*/))
{
//...
}
Does the closing brace call
s.Shutdown(SocketShutdown.Both);
s.Close();
s.Dispose();
Or only
s.Dispose();
?
(Or something else ?)
Thank you !
If I write
using (Socket s = new Socket(/*...*/))
{
//...
}
Does the closing brace call
s.Shutdown(SocketShutdown.Both);
s.Close();
s.Dispose();
Or only
s.Dispose();
?
(Or something else ?)
Thank you !
The using statement will call IDisposable.Dispose
and that is all.
The using statement is simply a compiler trick that allows you to more concisely express that you would always like to dispose of the given object even if the code contained by the block throws and roughly translates into the following
Socket s = new Socket(...)
try
{
// Code contained by the using... block here.
}
finally
{
s.Dispose();
}
In my experience the using statement is seldomly used in conjunction with the Socket
class. Most typically you would only call the Socket.Close
which will actually call Socket.Dispose
internally.
Close
calls Dispose
in the Socket
class in .NET. The using block just calls Dispose
.
But this doesn't mean that the using block is useless!
In .NET, using blocks are essentially just syntactic sugar for a try/finally where Dispose
is called on the object implementing the IDisposable
interface in the using statement. There are some differences as I illustrate and explain below.
The following code:
using (var socket = new Socket(/*...*/))
{
// operations
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
Expands to the following code at compile time:
{
Socket socket = new Socket(/*...*/);
try
{
// operations
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
finally
{
if (socket != null)
((IDisposable)socket).Dispose();
}
}
Not only are you getting a free null-check, but you're also creating an extra scope for your instance of Socket
class.
Ultimately, I would recommend using the using block in this case since it ensures that Dispose
is called on the instance of the Socket
class in the case of an exception being thrown, etc.
I can think of much to gain and literally nothing to lose when using a using block in this case. On the other hand, I can think of much to lose when not using the using block.
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.