【问题标题】:IDisposable cascadeIDisposable 级联
【发布时间】: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


【解决方案1】:

是的,这是正确的做法。

由于您有需要处理的依赖项,因此您必须确保它们一直被处理掉。否则,当您处理“外部设备类”时,底部的TcpClient 将无法正确处理,您可能会遇到资源泄漏(例如端口保持打开状态)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    相关资源
    最近更新 更多