如果一个对象使用 'using' 并且它被用在一些方法中,什么时候被释放

When is an object disposed if it uses 'using' and it is being used in a few methods

查看下面 class 中的这一特定代码行:using var ws = new ClientWebSocket()。考虑到它使用 using 并且它被用于一些更像 SendAsync、ReceiveAsync 等的方法,该对象何时被处置?如果它是在像 Main() 这样的常规方法中,它通常会在结束分支处被释放,但在这种情况下它不会被释放在那里。此 class 也不继承 IDisposable。我从 class.

中删除了不必要的细节
public class Client
{
    private ClientWebSocket? _ws;

    private async Task<bool> ConnectAsync(CancellationToken cancellationToken)
    {
        using var ws = new ClientWebSocket();
        _ws = ws;

        ...
    }

    public async Task SendAsync(string data)
    {
        ...

        await _ws.SendAsync(dataBytes, WebSocketMessageType.Text, true, CancellationToken.None);
    }
}

您的 using 语句是 C# 在 C# version 8 中引入的新的 using 声明样式,这意味着您的语句不再有不必​​要的嵌套。然而,原则仍然是一样的。考虑以下在 C# 8 之前编写代码的方式:

public class Client
{
    private ClientWebSocket? _ws;

    private async Task<bool> ConnectAsync(CancellationToken cancellationToken, string data)
    {
        using (var ws = new ClientWebSocket())
        {
            // When your code leaves this block, your websocket is disposed
            ws.SendAsync(dataBytes, WebSocketMessageType.Text, true, CancellationToken.None);
            
            // Assigning ws to _ws isn't necessary as it isn't usable outside your using statement
            _ws = ws;
            
            // The end of your using block - the websocket will now be disposed
        }
        
        // This line would fail as your websocket has been disposed
        _ws.SendAsync(dataBytes, WebSocketMessageType.Text, true, CancellationToken.None);
    }
}

当您的代码离开 using 块时,将调用 dispose 方法。声明意味着它被处理后的范围现在是包含 using 声明的代码块,在本例中是您的 ConnectAsync 方法。因此,即使在将它分配给 _ws 时您仍然引用它,它也不能使用,因为当您的代码离开此方法块时它已经被释放。