在使用子句中对类调用Close是有益的、有害的还是没有意义的?

本文关键字:有意义 调用 Close 子句 | 更新日期: 2023-09-27 18:08:38

在重构一些代码时,我添加了一个"using"语句,如下所示:

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

…但现在我想知道我是否可以或者应该取消关闭的召唤。我认为是这样,但这只是一种讲究(风格点)还是一种真正的必需品?

在使用子句中对类调用Close是有益的、有害的还是没有意义的?

这实际上取决于实现IDisposable的特定类。实现了IDisposable NOT的编写糟糕的类完全有可能正确释放资源并关闭连接。在SerialPort类的特定情况下,文档声明Close()调用Dispose()。我认为在这种情况下,你应该把它放在using块中,而不是手动调用Close()。

这真的取决于类,如果作者按照建议实现了它-正确实现了IDisposable,并且让Close除了调用Dispose()什么都不做。在这种情况下,Close()调用是多余的,可以在using块中包装类时删除。

一般来说,在SerialPort的特定情况下,他们这样做了,所以Close()调用是冗余的,可以删除。

按照Richter:

类型提供确定性地处理或封闭实现处置模式。处理模式定义了在定义类型时,开发人员应该遵守的约定要为类型的用户提供显式清理。

由于SerialPort定义了一个打开和关闭,这意味着它可以在其生命周期内多次打开和关闭,这与它被处理(例如永远不会再使用)是互斥的

但是回到你原来的问题,是的-在这种情况下,它是多余的,反编译SerialPort对象显示dispose在调用时为你关闭端口:

protected override void Dispose(bool disposing)
{
  if (disposing && this.IsOpen)
  {
    this.internalSerialStream.Flush();
    this.internalSerialStream.Close();
    this.internalSerialStream = (SerialStream) null;
  }
  base.Dispose(disposing);
}

如果在Dispose中出现异常情况,通常让Dispose抛出异常比静默完成要好(在任何特定情况下扼杀异常是否更好将取决于异常是否已经挂起,而且目前还没有机制可以通过Dispose知道何时是这种情况)。因为没有好的方法来处理Dispose中的异常,所以在可能的情况下,确保在Dispose中执行的任何可能出错的操作将在Dispose调用之前完成,这通常是一个好主意。

如果Dispose是正常情况下唯一的清理方法,那么让它抑制异常将会带来一个重大的风险,即问题可能发生但未被发现。让一个类同时支持Closeusing,并让客户端在主线情况下调用Close,将允许降低这种风险(如果异常挂起,Dispose将在没有Close的情况下被调用,因此清除时的任何异常将被抑制,但代码将知道由于挂起的异常而在某处出错;如果在Close之前没有异常发生,那么它没有在Dispose清理上下文中被调用的事实将意味着它可以假设没有异常挂起,因此它可以安全地抛出自己的异常)。

DisposeClose的异常处理实践中没有太多的一致性,但我原则上建议调用Close。根据DisposeClose的实现方式,在隐式Dispose之前显式调用Close可能有帮助,也可能没有帮助,但它应该是无害的。考虑到它可能会有所帮助(如果不是在当前版本的类中,也许在将来的版本中),我建议将其作为一般习惯。