Calling dispose() for Font in Windows form

2019-07-02 23:36发布

问题:

I've been running into the same issue as described in this question. That is, Fortify complained about the creation of font objects, for which the new Font() statements are generated code in the designer.cs files. When looking at profiling results I do get the impreesion I need to do something about this, at least in some cases.

This is, of course, an issue only if the develper has assigned a font of his choice to the form in the graphical designer. My plan is to undo that choice and to create the Font manually after the call to InitializeComponent() and then call dispose() for the Font in the dispose() method of the form. Since that way I do create the resource myself (and checked whether it is used elsewhere) I'm sure it is not shared and can safely allow it's disposal. Up to that point I'm rather confident about the issue.

Now the dispose() method of the form is generated as well when the form is created and has a boolean disposing parameter. What I'm uncertain about (and this is my question) is whether I can ignore this parameter, or have to check it for true or false before calling font.dispose(). (I have to admit I do not yet understand the dispose logic in these generated winforms).

More specifically: the generated code looks as follows:

    /// <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);
    }

Assuming a font for form 'myForm' is affected, I'd create it using

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

and would call this.myForm.Dispose()to dispose it. The question is, where in the forms' dispose() method this should go.

回答1:

The question is, where in the forms' dispose() method this should go.

Here is a simple rule from Microsoft:

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

   // Free any unmanaged objects here. 
}

Read this documentation for more details.

So if your font is loaded from a font file, for instance, then it is unmanaged and you should dispose it outside the if (disposing) block.



回答2:

Control font properties are weird. With most controls, setting the Font property will cause a control to take a snapshot of that Font's characteristics and render itself appropriately. The control will not dispose of the font, nor will it care if the font is disposed; even if the font is disposed before it's assigned the control's Font property the control will still take a snapshot of the font's characteristics (which remain readable to the control's snapshot method even when a font is disposed) and use that. Note that not all controls work this way, and I don't know how to emulate this behavior with user controls that do their own drawing. Nonetheless, with some types of controls, the seemingly-nonsensical

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

will work just fine. Even

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

would work. I suspect Font was designed before Microsoft realized the "ownership" problems posed by sharable immutable disposable objects; auto-generated code is very sloppy with Dispose semantics, so it's probably not necessary to do too much better in most cases.