简体   繁体   中英

using block with Socket

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM