如何创建一次性类

本文关键字:一次性 创建 何创建 | 更新日期: 2023-09-27 18:18:50

我有这个'PlayerClass'类,每次我实例化它时,我需要处置它,包括该类中的字段。有办法吗?这是我的班级:

internal class PlayerClass 
{
    public WindowsMediaPlayer _wplayer;
}

我如何得到处置类后使用它?我试着在互联网上找到一种方法,但测试后都没有工作。

我试过了:

internal class PlayerClass : IDisposable
{
    public WindowsMediaPlayer _wplayer;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    /// <summary>
    /// Is this instance disposed?
    /// </summary>
    protected bool Disposed { get; private set; }
    
    /// <summary>
    /// Dispose worker method. See http://coding.abel.nu/2012/01/disposable
    /// </summary>
    /// <param name="disposing">Are we disposing? 
    /// Otherwise we're finalizing.</param>
    protected virtual void Dispose(bool disposing)
    {
        Disposed = true;
    }
}

我做错了什么?

如何创建一次性类

看起来您正在实现IDisposable只是为了检查它,这对于托管代码来说是不必要的。垃圾回收器会在你身后自动清理。

你可能需要在你的文章中澄清为什么你正在实施IDisposable

然而,我认为你的错误是Dispose()不是由垃圾收集器自动调用。如果您实现IDisposable,您必须确保使用您的类的代码要么在using()语句中实例化,要么手动调用.Dispose。否则你的dispose方法将永远不会触发。

using(var player = new PlayerClass()){
    // Do something with player
    // player.Dispose() is called automatically when you exit this using statement.
}

由于您依赖于调用者来确保调用Dispose,因此您可能还需要查看SafeHandle(首选)或Finalize

因为IDisposable.Dispose的实现是由当实例所拥有的资源为none时,类型的消费者如果需要的话,您应该将托管对象包装在SafeHandle(推荐的替代方案),或者您应该重写. _ Object.Finalize来释放非托管资源消费者忘记调用Dispose.

来源:IDisposable Interface

使用声明

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement

与其他答案的建议相反,对所有实现Dispose()方法(即实现IDisposable)的创建对象Dispose是必要的。这些对象是非托管资源,因此对GC是不可见的。不处理它们肯定会导致内存泄漏。(请注意,有些术语更倾向于使用Close()方法而不是Dispose方法,在这种情况下,Close()方法应该是相同的。)

这是IDisposable接口的最佳实践实现。

#region IDisposable implementation with finalizer
private bool isDisposed = false;
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
protected virtual void Dispose(bool disposing) {
  if (!isDisposed) {
    if (disposing) {
      if (_wplayer != null)     _wplayer.Dispose();
   }
  }
  isDisposed = true;
}
#endregion

以下是来自以上MSDN链接的应该不应该的最佳实践:

  • DO声明一个受保护的虚void Dispose(bool Dispose)方法集中所有与释放非托管资源相关的逻辑。
  • DO通过简单地调用Dispose(true)和GC.SuppressFinalize(this)来实现IDisposable接口。
  • DO NOT使无参数的Dispose方法为虚方法。
  • 不要声明Dispose方法的任何重载,除了Dispose()和Dispose(bool)。
  • DO允许Dispose(bool)方法被多次调用。方法可能在第一次调用后选择什么都不做。
  • AVOID从Dispose(bool)内部抛出异常,除非在包含进程已损坏的关键情况下(泄漏,不一致的共享状态等)。
  • 考虑提供方法Close(),除了Dispose(),如果Close是该领域的标准术语。

来自MSDN文档

提供释放非托管资源的机制。

您不需要处置托管对象,. net将为您提供此功能。当您创建的互操作类将导致非托管资源时,它是有用的,然后您可以处置所有对象。