【问题标题】:Implementing IDisposable C#实现 IDisposable C#
【发布时间】:2017-04-08 06:22:41
【问题描述】:

我在理解 IDisposable 接口时遇到了一点问题

我正在开发一个游戏引擎,并对我的解决方案进行了代码分析,并被告知要在我的“GrapicsEngine”类上实现 IDisposable 接口,因为它包含一个位图实例。

当然,我搜索了互联网以了解如何正确执行此操作并想出了以下代码:

这是我的班级成员:

private const int BITMAP_WIDTH = 4096;
private const int BITMAP_HEIGHT = 4096;

private Graphics backBuffer;
private Bitmap bitmap;

private Color clearColor;

private WindowSurface surface;

private GraphicsQuality quality;

private Viewport viewport;

这是我的 IDispoable 区域:

#region IDisposable

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing == true)
        ReleaseManagedResources();

    ReleaseUnmanagedResources();
}

private void ReleaseManagedResources()
{
    if (bitmap != null)
        bitmap.Dispose();
    if (backBuffer != null)
        backBuffer.Dispose();
}

private void ReleaseUnmanagedResources()
{

}

~GraphicsEngine()
{
    Dispose(false);
}

#endregion

请注意,WindowSurface 是一个 WinForm 面板,GraphicsQuality 是一个枚举,而 Viewport 仅包含 int 值。

所以我只有几个问题:

  1. 我是否妥善处理了我的资源?
  2. 我应该在非托管资源方法中处理哪些资源
  3. 如果我创建一个新类并且它包含我的 GraphicsEngine 类,该类是否也应实现 IDisposable?

我们将不胜感激有关此主题的任何帮助。

【问题讨论】:

    标签: c# bitmap game-engine idisposable


    【解决方案1】:

    你在正确的轨道上。任何时候你有一个一次性的类级别变量,包含的类也应该是一次性的。据我所知,你正在妥善处理它。我没有看到类名行,所以我无法判断您是否包含 IDisposable 接口,但我想您会这样做,因为您已经实现了这些方法。如果不确定,请确保添加它。
    IDisposable 是一种连锁反应类型的实现。如果变量是一次性的,并且它只是方法调用的本地变量,那么您在调用结束时将其处理掉,但如果它在类级别,您可以实现 IDisposable 并在您的类中处理它。这样任何使用你的类的人都可以正确地处理它。

    例如:假设我在课堂上打开了一个文件...

    public class MyClass
    {
         private File txtFile = File.Create(...)
    }
    

    现在有人使用我的课程。

    private void useClass()
    {
         var myClass = new MyClass();
    }
    

    嗯,他们刚刚打开了一个文件,但没有正确处理。

    修改代码,就可以这样使用了……

    public sealed class MyClass : IDisposable
    {
         private File txtFile = new File.Create(...)
    
         public void Dispose()
         {
              txtFile.Dispose();
              GC.SuppressFinalize(this);
         }
    
         ~MyClass() => Dispose();
    }
    

    当使用它时,他们可以像这样使用它......

    private void useClass()
    {
         using (var myClass = new MyClass())
         {
             //some code
         }
    }
    

    希望这能回答您的问题。请记住,如果您声明一个方法本地的一次性对象,那么您不必在您的类中实现 IDisposable 因为您将在该方法中处理它。但是,如果您在类级别范围内实现它,无论您是否有处理它的方法,您都应该实现 IDisposable 并检查以确保它在包含类调用 dispose 时被释放。有道理? 希望这会有所帮助。

    【讨论】:

    • 我想我现在明白了。最后一个问题:我有一个 Sprite 类,它包含一个具有公共 getter 和 setter 的位图,这个调用是否也应该实现 IDisposable,或者我应该在需要时像“sprite.bitmap.Dispose”一样处理位图?我想是后者。
    • 贴出部分代码,我会告诉你的。如果您通过属性(getter / setter)将一次性对象传回,则对象本身是一次性的,使用该属性的任何人都可以选择将其与一次性功能一起使用。但同样,是的,因为这是在类级别,你仍然希望在你的类中实现和处理它。
    • 我想我现在明白了,谢谢。最后一个问题,我有一个动画帧列表,一个帧包含一个位图。当我处理框架(通过遍历列表)时,当涉及到处理非托管资源时,我应该在这里清除我的列表吗?
    • 我不确定我是否理解正确。您是否在问是否应该迭代列表并处理对象以及完成后清除列表?您肯定需要处理这些对象,这很好,但您是否清除列表是一​​种设计选择。我可能会,但是对已处置对象的引用可以为您提供信息(已处置),并且如果很明显您什么都不知道。所以这取决于你对列表做了什么。
    猜你喜欢
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 2011-01-30
    • 2013-10-29
    • 2023-03-28
    相关资源
    最近更新 更多