【发布时间】:2020-07-17 07:55:17
【问题描述】:
我有一个类通过 TCP/IP 为外部设备建模。这个类创建一个客户端,它基本上是 System.Net.Sockets.TcpClient 的一个包装器,这个类的实例由一个应用程序类保存。
根据https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose#cascade-dispose-calls,如果一个类拥有一个实现 IDisposable 的字段,它也应该实现 IDisposable。
所以在我的情况下,TcpClient 实现了 IDisposable,因此我的客户端类必须实现 IDisposable,因此我的外部设备类必须实现 IDisposable,因此我的应用程序类必须实现 IDisposable。
听起来很麻烦,所以我怀疑这样做是否正确?
public class Client : IDisposable
{
private TcpClient _tcpClient;
...
public void Connect()
{
_tcpClient = new TcpClient();
if (!_tcpClient.ConnectAsync(address, port).Wait(1000))
...
}
public void Disconnect()
{
_tcpClient?.Dispose();
_tcpClient = null;
}
#region IDisposable
...
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
_tcpClient?.Dispose();
_tcpClient = null;
}
_disposed = true;
}
#endregion
...
}
public class SM15k : IDisposable
{
private readonly Client _client;
...
public SM15k()
{
_client = new Client();
}
#region IDisposable
...
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
_client.Dispose();
}
_disposed = true;
}
#endregion
...
}
public class App : IDisposable
{
private SM15k _SM15k;
#region IDisposable
...
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
_SM15k?.Dispose();
_SM15k = null;
}
_disposed = true;
}
#endregion
...
}
【问题讨论】:
-
你在使用 IoC 吗?
-
“因此我的应用程序类必须实现 IDisposable” - 不,您的应用程序类应该在完成使用外部设备类后触发处置。或者至少没有什么可以调用ApplicationClass.Dispose(),所以不需要在那里添加接口。
-
你应该这样做吗? 理论上 - 是的。在实践中,这并不重要。 stackoverflow.com/a/44158572/34092
-
@mjwills 对于在关闭时可能很好并清理干净的托管资源,但如果您的应用程序分配了非托管资源(例如 tcp 端口),它将不会自动关闭。此外,这个类可能会在长时间运行的应用程序中重复使用多次,然后无论如何都应该这样做。
标签: c# idisposable