关于具体案例的一次性问题
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 中实现终结器。
问题 #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 中实现终结器。