可释放对象级联。

3

我有一个用于通过TCP/IP建模外部设备的类。这个类创建了一个客户端,基本上是System.Net.Sockets.TcpClient的包装器。应用程序类持有这个类的实例。

根据https://learn.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)吗? - mjwills
请提供一个 [mcve]。 - mjwills
你应该这样做吗?理论上,是的。但实际上,这并不重要。 - mjwills
对于可能在关闭时被清理的托管资源而言,这样做可能是可以的,但如果您的应用程序已经分配了未受管理的资源(例如TCP端口),它将不会自动关闭。此外,这个类可能会在长时间运行的应用程序中被多次重复使用,因此无论如何都应该完成。 - Karl-Johan Sjögren
非托管资源最常见的类型是封装操作系统资源的对象,例如文件、窗口、网络连接或数据库连接。虽然垃圾回收器能够跟踪封装非托管资源的对象的生命周期,但它不知道如何释放和清理非托管资源。 - Karl-Johan Sjögren
显示剩余4条评论
1个回答

3

是的,这是正确的方法。

由于你有需要被处理的依赖项,所以你必须确保它们一直被处理。否则,当你处理“外部设备类”时,底层的TcpClient可能无法得到正确的处理,可能会出现资源泄漏(例如,端口仍然打开)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接