Muh*_*eed 5 .net c# idisposable .net-core
对于IDisposable,我经常使用抽象基类,因为实现它非常困难。主要是因为您可以使用该接口来处理托管和非托管引用,并且每个引用的处理方式都不同。
public abstract class Disposable : IDisposable
{
~Disposable() => this.Dispose(false);
public bool IsDisposed { get; private set; }
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void DisposeManaged() {}
protected virtual void DisposeUnmanaged() {}
protected void ThrowIfDisposed()
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
}
private void Dispose(bool disposing)
{
if (!this.IsDisposed)
{
if (disposing)
{
this.DisposeManaged();
}
this.DisposeUnmanaged();
this.IsDisposed = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用IAsyncDisposable,我找不到参考实现。另外,我相信它只处理托管资源,主要是因为它太新了,并且没有需要异步处理的非托管资源。这样对吗?如果是这样,那么实现是微不足道的吗?
更新: .NET 文档现在有一篇文章实现 DisposeAsync 方法,描述了需要支持同步和异步处置的非密封类的推荐 IAsyncDisposable 实现。它建议添加单独的虚拟 DisposeAsyncCore 方法:
using System;
using System.Text.Json;
using System.Threading.Tasks;
public class ExampleAsyncDisposable : IAsyncDisposable, IDisposable
{
// To detect redundant calls
private bool _disposed = false;
// Created in .ctor, omitted for brevity.
private Utf8JsonWriter _jsonWriter;
public async ValueTask DisposeAsync()
{
await DisposeAsyncCore();
Dispose(false);
GC.SuppressFinalize(this);
}
protected virtual async ValueTask DisposeAsyncCore()
{
// Cascade async dispose calls
if (_jsonWriter != null)
{
await _jsonWriter.DisposeAsync();
_jsonWriter = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_jsonWriter?.Dispose();
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
_disposed = true;
}
}
Run Code Online (Sandbox Code Playgroud)
该示例假设只能异步处置间接拥有的非托管资源。直接拥有的托管资源始终在protected virtual void Dispose方法中同步处置。
旧答案:与常规方法不同,DisposeAsync 方法不应Dispose从终结器调用。终结器已经在专用线程中运行,并且不会阻止任何内容,因此没有必要。因此,DisposeAsync始终可以处置非托管和托管资源,并且不需要实现单独的DisposeAsync(bool disposing)方法。
实现示例可以在新的 .NET Core 类型Utf8JsonWriterIAsyncDisposable的源代码中找到(它是一个密封类,因此不使用虚方法):
public async ValueTask DisposeAsync()
{
if (_stream == null)
{
// The conditions are ordered with stream first as that would be the most common mode
if (_output == null)
{
return;
}
}
await FlushAsync().ConfigureAwait(false);
ResetHelper();
_stream = null;
_arrayBufferWriter = null;
_output = null;
}
Run Code Online (Sandbox Code Playgroud)
基本上,它应该做与常规一次性模式相同的事情Dispose(true),但如果可能的话,是异步的。如果无法异步处理,但由于某种原因您仍然需要实现此接口,则可以回退到同步处理并返回已完成的 ValueTask,如System.IO.Stream中所做的那样。