关于具体案例的一次性问题

IDisposable questions about specific case

问题 #1:

StartAsync 处理 _clientWebSocket_tokenSource 的处置。那么我真的需要在 Dispose() 中处理这些吗?我想我应该只在 Dispose() 中保留 _semaphore.Dispose(),因为我的代码已经处理了其余部分。

问题 #2:

如果用户忘记调用 Dispose() 或将其包装在 using 中怎么办?通常通过在 deconstructor/finalizer 中调用 Dispose() 来解决,但在这种情况下,我的 class 是 sealed.

public sealed class Client : IDisposable
{
    private readonly SemaphoreSlim _semaphore = new(1, 1);

    private ClientWebSocket? _clientWebSocket;
    private CancellationTokenSource? _tokenSource;

    public void Dispose()
    {
        _semaphore.Dispose();

        // TODO: Do I need to dispose these since my code below does that? 
        _clientWebSocket?.Dispose();
        _clientWebSocket = null;

        _tokenSource?.Cancel();
        _tokenSource = null;
    }

    public Task StartAsync()
    {
        _clientWebSocket = new ClientWebSocket();
        _tokenSource = new CancellationTokenSource();

        try
        {
            ...
        }
        catch (Exception ex)
        {
        }
        finally
        {
            _clientWebSocket?.Dispose();
            _clientWebSocket = null;

            _tokenSource?.Cancel();
            _tokenSource = null;
        }
    }

    public ValueTask SendAsync()
    {
        if (_clientWebSocket is { State: WebSocketState.Open })
        {
            return;
        }

        ...
    }
}

StartAsync handles the disposal of _clientWebSocket and _tokenSource. So do I really need to dispose these in Dispose() as well? I think I should keep _semaphore.Dispose() only in the Dispose(), because my code already handles the disposal of the rest.

那为什么是字段呢?听起来它们应该是局部变量,在这种情况下它们不会成为您 class' dispose 方法的一部分。

同时忘记您正在使用的模式,改用 using

What if the user forgets to call Dispose() or wrap it in using?

这是他们的选择,但有一个 Roslyn 分析器警告:CA2000

It's usually solved by calling Dispose() in the deconstructor/finalizer

不经常,经常,但你是对的。如果调用者不这样做,您希望您的终结器在您的对象之后清理,并带有明显的线程警告(终结器 运行 将在哪个线程上?该问题的答案阻止您在终结器中处理 OpenGL 句柄例如)。

in this case my class is sealed

这与你的问题无关,你可以在密封的 classes 中实现终结器。