1

In refactoring some code, I added a "using" statement like so:

using (SerialPort serialPort = new SerialPort())
{
    serialPort.BaudRate = 19200;
    serialPort.Handshake = Handshake.XOnXOff;
    serialPort.Open();
    serialPort.Write(cmd);
    serialPort.Close();
}

...but now wonder whether I can or should do away with the call to Close. I reckon so, but is it just a nicety (style points) or a veritable necessity?

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 2
    http://referencesource.microsoft.com/#System/sys/system/io/ports/SerialPort.cs#ae0a3218c6c9f7fe – SLaks Jun 13 '14 at 20:41

4 Answers4

4

It really depends on the class and if the author implemented it as recommended - implemented IDisposable correctly, and have Close do nothing but call Dispose(). In such a case, the Close() call is redundant and can be removed when wrapping the class in a using block.

This is generally speaking - in this specific case with SerialPort, they did so, so the Close() call is redundant and can be removed.

Gjeltema
  • 4,122
  • 2
  • 24
  • 31
4

It really depends on the particular class implementing IDisposable. It's perfectly possible for a badly written class that implements IDisposable NOT to properly release resources and close connections. In the specific case of the SerialPort class, the documentation states that Close() calls Dispose(). I think you should in this case be fine to put it in a using block and not call Close() manually.

Marius George
  • 526
  • 2
  • 6
1

As per Richter:

Types that offer the capability to be deterministically disposed of or closed implement the dispose pattern. The dispose pattern defines conventions a developer should adhere to when defining a type that wants to offer explicit cleanup to a user of the type.

Being that SerialPort defines an open and close it implies that it can be opened and closed multiple times during it's lifetime, which is mutually exclusive from it being disposed (e.g. never used again)

But back to your original question, yes - in this case it is redundant, decompiling the SerialPort object reveals that dispose closes the port for you when called:

protected override void Dispose(bool disposing)
{
  if (disposing && this.IsOpen)
  {
    this.internalSerialStream.Flush();
    this.internalSerialStream.Close();
    this.internalSerialStream = (SerialStream) null;
  }
  base.Dispose(disposing);
}
Eric Scherrer
  • 3,328
  • 1
  • 19
  • 34
  • In my case I was running into a "File 55" error when my method was called several times, so I was trying to find a way to tame that beast. I should have thought of referencing Richter, due to the earthquake-like results I was getting. – B. Clay Shannon-B. Crow Raven Jun 13 '14 at 20:58
1

If an exceptional condition arises in Dispose, it is usually better to have Dispose throw the exception than complete silently (whether it's better to stifle the exception in any particular situation will depend upon whether an exception is already pending and there is as yet alas no mechanism via which Dispose can know when that's the case). Because there is no good way to handle an exception within Dispose, it's often a good idea to ensure when possible that any actions which could go wrong if done within a Dispose will be done before the Dispose is invoked.

If Dispose were the only method of cleanup in the normal case, then having it stifle exceptions would pose a significant risk that problems could occur but go undetected. Having a class support both Close and using, and having clients call Close in the main-line case, will allow such risk to be reduced (if an exception is pending, Dispose will get called without Close, and thus any exceptions on cleanup will get stifled but code will know that something went wrong somewhere because of the pending exception; if no exception occurs before Close, the fact that it's not being called in a Dispose cleanup context will mean that it can assume no exception is pending, and it may thus safely throw one of its own).

There's not much consistency in the exception-handling practices of Dispose and Close, but I would recommend calling Close on principle. Depending upon how Dispose and Close are implemented, explicitly calling Close before the implicit Dispose may or may not be helpful, but it should be at worst harmless. Given the possibility of its being helpful (if not in the present version of a class, perhaps in a future version) I would suggest it as a general habit.

supercat
  • 77,689
  • 9
  • 166
  • 211