C# 处理图形对象

C# 处理图形对象,c#,winforms,graphics,dispose,idisposable,C#,Winforms,Graphics,Dispose,Idisposable,我被处理图形对象的机械原理弄糊涂了。处理字体和笔等对象的最佳方法是什么?在实例化/处置它们时,最好的做法是什么?我的意思是类中的字段还是方法中的变量 例如,我有一个类似以下代码的类。我有一些字体和笔,它们在类中的每个地方都使用,所以我不是每次在调用方法时都创建它们,而是将它们创建为字段。这会提高性能吗 public class PackageDrawer : IDisposable { Font font1 = .... Font font2 = .... Font font3

我被处理图形对象的机械原理弄糊涂了。处理字体和笔等对象的最佳方法是什么?在实例化/处置它们时,最好的做法是什么?我的意思是类中的字段还是方法中的变量

例如,我有一个类似以下代码的类。我有一些字体和笔,它们在类中的每个地方都使用,所以我不是每次在调用方法时都创建它们,而是将它们创建为字段。这会提高性能吗

public class PackageDrawer : IDisposable
{
   Font font1 = ....
   Font font2 = ....
   Font font3 = ....
   Pen  pen1 = ...
   Pen  pen2 = ...
   Pen  pen3 = ...

   public Bitmap Draw()
   {
       //use fonts and pens here
       //also they are being user in more methods
   }

   ~PackageDrawer()
   {
       Dispose();
   }

   public void Dispose()
   {
       font1.Dispose();
       //And dispose other stuff...
   }
}

一般来说,
画笔
画笔
对象的分配越晚越好,而
处理(…)
越快越好。通常在主(假设的)
Paint(…)
方法中处理。这就是几乎所有框架中的绘图工件(并且
.NET
也不例外)都像结构一样声明,以保证
堆栈上的快速分配和快速销毁

一般来说,
Pen
Brush
对象最好尽可能晚地分配,并且
Dispose(…)
越快越好。通常在主(假设的)
Paint(…)
方法中处理。这就是几乎所有框架中的绘图工件(并且
.NET
也不例外)都像结构一样声明,以保证
堆栈上的快速分配和快速销毁

处理字体和笔等对象的最佳方法是什么

最好也是唯一的方法是调用
Dispose()
当您不再需要它们时,您应该将它们处理掉

在实例化/处置它们时,最好的做法是什么

这一切都取决于您的实现。在大多数情况下,最好在处理完它们后立即创建和销毁它们。这一切实际上取决于客户端代码如何实现
PackageDrawer
对象以及可能访问这些对象的方法

您可能需要阅读StackOverflow上的
IDisposable
。从您发布的内容中,您可以删除
~PackageDrawer()
终结器覆盖,只需创建一个
Dispose()
方法即可。如果从该方法派生任何类,您可能还希望将
Dispose
方法设置为虚拟

此外,没有任何东西阻止在对象上多次调用
Dispose()
,因此您需要添加一个私有跟踪布尔值,以确保它不会多次尝试和
Dispose()
。另外,在尝试调用
Dispose()
之前,请始终对对象执行null检查,以避免出现
NullReferenceException

private bool _isDisposed;

public void Dispose()
{
    Dispose(true);
}

protected virtual void Dispose(bool disposing)
{
   if (_isDisposed)
      return;

   if (disposing)
   {
       if (font != null)
           font.Dispose();
   }

   _isDisposed = true;

}
处理字体和笔等对象的最佳方法是什么

最好也是唯一的方法是调用
Dispose()
当您不再需要它们时,您应该将它们处理掉

在实例化/处置它们时,最好的做法是什么

这一切都取决于您的实现。在大多数情况下,最好在处理完它们后立即创建和销毁它们。这一切实际上取决于客户端代码如何实现
PackageDrawer
对象以及可能访问这些对象的方法

您可能需要阅读StackOverflow上的
IDisposable
。从您发布的内容中,您可以删除
~PackageDrawer()
终结器覆盖,只需创建一个
Dispose()
方法即可。如果从该方法派生任何类,您可能还希望将
Dispose
方法设置为虚拟

此外,没有任何东西阻止在对象上多次调用
Dispose()
,因此您需要添加一个私有跟踪布尔值,以确保它不会多次尝试和
Dispose()
。另外,在尝试调用
Dispose()
之前,请始终对对象执行null检查,以避免出现
NullReferenceException

private bool _isDisposed;

public void Dispose()
{
    Dispose(true);
}

protected virtual void Dispose(bool disposing)
{
   if (_isDisposed)
      return;

   if (disposing)
   {
       if (font != null)
           font.Dispose();
   }

   _isDisposed = true;

}

您不需要定稿人,也不应该使用它来调用
Dispose
,因为无法保证字段尚未定稿。@Lee您能再解释一下吗?您所说的“字段尚未最终确定”是什么意思?无法保证最终确定程序的执行顺序,因此在运行
PackageDrawer
的最终确定程序时,其字段的最终确定程序可能已经执行。您的最终用户无法执行任何操作,因此应将其删除。您不需要最终用户,也不应使用它调用
Dispose
,因为无法保证字段尚未最终用户。@Lee您能再解释一下吗?您所说的“字段尚未最终确定”是什么意思?无法保证最终确定程序的执行顺序,因此在运行
PackageDrawer
的最终确定程序时,其字段的最终确定程序可能已经执行。您在Finalizer中无法执行任何操作,因此应该将其删除。
Brush
是一种引用类型,而不是值类型。我所知道的.net中唯一实现
IDisposable
的图形相关类型是类类型。实际上,我能想到的唯一实现
IDispose
struct
类型是实现继承该接口的其他接口(通常是
IEnumerator
)的结果;实际上,它们都没有对IDisposable.Dispose做任何响应。
@supercat:事实上,我在回答中没有提到一次性
结构
,我写了destroy(以某种方式)。
Brush
是一种引用类型,不是值类型。据我所知,在.net中实现
IDisposable
的唯一图形相关类型是类类型。实际上,我能想到的唯一实现
IDispose
struct
类型是实现继承该接口的其他接口(通常是
IEnumerator
)的结果;它们中没有一个对IDisposable.Dispose做出响应