【问题标题】:Automatic Disposal Extension Method reasonable?自动处理扩展方法合理吗?
【发布时间】:2011-04-22 21:38:24
【问题描述】:

我一直在编写一些自定义 WinForm 控件,它们进行大量绘图,因此往往有很多基于一次性图形的字段(画笔、钢笔、位图等),因此我的控件Dispose() 方法必须对它们中的每一个调用 Dispose。

我担心我(或未来的维护者)很容易错过需要释放的字段,要么忘记释放它,要么没有意识到它实现了 IDisposable。因此,我在 Object 上编写了一个非常简单的扩展方法,它可以找到所有 IDisposable 字段并处理它们:

static public void DisposeAll(this Object obj)
{
   var disposable = obj.GetType()
                       .GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                       .Select(fi => fi.GetValue(obj))
                       .Where(o => o != null && o is IDisposable)
                       .Cast<IDisposable>();

   foreach (var d in disposable) d.Dispose();
}

我的问题基本上是这样做是否合理。我想不出它可能会搞砸什么,但是我对 WinForms 的内部工作并不是特别熟悉,这似乎是一种可能会导致恼人的错误的事情(弄乱反射和处置)。

【问题讨论】:

  • 您可以将WhereCast 调用替换为.OfType&lt;IDisposable&gt;()
  • 谢谢。 OfType 扩展是否也检查空值?我想不会。

标签: c# .net extension-methods dispose


【解决方案1】:

不,这不是一个好方法。您在 OnPaint 方法中创建的绘图对象应该始终是局部变量,由 using 语句包装。您的方法需要声明一个类,只是为了存储这些对象。痛苦而低效。此外,您将处置不应处置的对象。就像预制笔和画笔一样,例如 Pens.Black。

【讨论】:

    【解决方案2】:

    很难说它是否适用于您的特定情况;我按照Dispose() 调用的顺序看到了最大的问题。如果一个非托管句柄依赖于另一个句柄,那么您将在绘图、内存等方面遇到奇怪的问题。

    恕我直言。

    【讨论】:

      【解决方案3】:

      您可以使用FxCopCode Analysis(Visual Studio 2010 Premium 或更高版本)。

      规则CA2213 将查找您忘记处置的字段。

      【讨论】:

        【解决方案4】:

        我认为这很危险。如果你实现了这个想法,那么对象将被释放(如果它是一次性的),并且在某些情况下,比如当你需要对象存在时,它就会消失。

        自动化对于您确定它们根本不会被引用的对象有好处。

        【讨论】:

          【解决方案5】:

          通常您不想处置所有一次性成员。例如。对父表单的引用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-15
            • 1970-01-01
            • 2022-01-23
            相关资源
            最近更新 更多