【问题标题】:Calling dispose() for Font in Windows form在 Windows 窗体中调用字体的 dispose()
【发布时间】:2014-03-26 12:44:46
【问题描述】:

我遇到了与this question 中描述的相同的问题。也就是说,Fortify 抱怨字体对象的创建,new Font() 语句是在 Designer.cs 文件中生成的代码。在查看分析结果时,我确实觉得我需要对此做一些事情,至少在某些情况下是这样。

当然,只有当开发人员已将他选择的字体分配给图形设计器中的表单时,这才是一个问题。我的计划是撤消该选择并在调用InitializeComponent() 之后手动创建字体,然后在表单的dispose() 方法中为字体调用dispose()。由于这种方式我自己创建了资源(并检查了它是否在其他地方使用),我确信它不是共享的并且可以安全地允许它被处置。到目前为止,我对这个问题相当有信心。

现在表单的dispose() 方法在创建表单时也会生成,并且有一个布尔值disposing 参数。我不确定(这是我的问题)是我是否可以忽略这个参数,或者在调用font.dispose() 之前必须检查它的真假。 (我不得不承认我还不了解这些生成的 winform 中的 dispose 逻辑)。

更具体地说:生成的代码如下所示:

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

假设表单“myForm”的字体受到影响,我将使用它来创建它

... 
InitializeComponent(); // this is generated into the constructor
this.myForm.Font = new System.Drawing.Font("NiftFontName",...);
...

并会打电话给this.myForm.Dispose()来处理它。问题是,表单的dispose() 方法应该放在哪里。

【问题讨论】:

  • 不,不要那样做。字体是非常昂贵的创建对象,它们保存在缓存中,因此重用起来很便宜。 Fortify 还不够聪明,无法知道这一点。微软代码分析器是,它可以读取Font类所具有的[SuppressMessage]属性。

标签: c# winforms fonts dispose idisposable


【解决方案1】:

问题是,这应该放在表单的 dispose() 方法的哪个位置。

这是来自 Microsoft 的一个简单规则:

protected virtual void Dispose(bool disposing)
{
   if (disposing) {
      // Free any managed objects here. 
   }

   // Free any unmanaged objects here. 
}

阅读this documentation了解更多详情。

因此,例如,如果您的字体是从字体文件加载的,那么它是非托管的,您应该将它放在 if (disposing) 块之外。

【讨论】:

    【解决方案2】:

    控制字体属性很奇怪。对于大多数控件,设置Font 属性将导致控件拍摄Font 特征的快照并适当地呈现自身。控件不会处理字体,也不关心字体是否被处理;即使字体在分配控件的Font 属性之前被释放,该控件仍会拍摄字体特征的快照(即使释放了字体,控件的快照方法仍然可以读取这些特征)和用那个。请注意,并非所有控件都以这种方式工作,而且我不知道如何使用自己绘制的用户控件来模拟这种行为。尽管如此,对于某些类型的控件,看似荒谬的

    using (Font myFont = new Font(Whatever))
      theButton.Font = myFont;
    

    可以正常工作。甚至

    myFont = new Font(Whatever);
    myFont.Dispose();
    theButton.Font = myFont;
    

    会起作用的。我怀疑Font 是在微软意识到可共享不可变一次性对象所带来的“所有权”问题之前设计的;自动生成的代码在 Dispose 语义上非常草率,因此在大多数情况下可能没有必要做得更好。

    【讨论】:

    • 那么就不用使用 using 构造了吗?
    • @Revious:在 Font 对象专门用于设置控件属性的情况下,IDisposable 的正常使用模式似乎并不真正适用,因为 @ 987654330@ 将仅清除设置控件属性时不需要的部分对象。但是,此类模式适用于大多数其他类型的 IDisposable 对象。
    • 谢谢,如果我使用字体和其他对象进行 GDI 绘图,垃圾收集器应该在我退出定义它们的代码块后立即收集它们?
    • @Revious:已处理的Font 将不再可用于 GDI 绘图。但是,设置控件的Font 属性不会导致控件使用该字体进行绘图,而是会导致它制作字体属性的副本——即使在处置Font 之后也可以这样做。
    • @Revious:我认为如果有单独的FontDescription 和DrawingFont 类型,.NET 设计会更简洁;后者适用于 GDI 绘图并实现IDisposable,而前者用于设置控件属性但不会实现IDisposable。不过,这个设计现在已经很好地锁定了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 2010-10-18
    相关资源
    最近更新 更多