Search code examples
c#fontsdispose

Should I dispose of an old font in the setter of a font property?


I have a settings object for reports that has a number of Fonts in it.

They are defaulted like this

public Font TitleFont { get; set; } = new Font("Arial", 8, FontStyle.Bold);

but they can get changed in numerous places before being used for gdi+ rendering of reports. This is not in a winForms control.

Fonts implement IDisposable so should I dispose of the old font in the setter for the property? Or should I store the Fontname, size and style as 3 properties and only create the font when it's needed?


Solution

  • The main question here is if the class is reponsible for the font. When yes, it should Dispose the font:

     public class MyFontStorage: IDisposable {
       private Font m_MyFont; 
       ... 
       public Font MyFont {
         get {
           return m_MyFont; 
         } 
         set {
           if (m_MyFont == value)
             return;
    
           if (m_MyFont != null)
             m_MyFont.Dispose();
    
           m_MyFont = value;             
         }  
       }
    
       protected virtual void Dispose(bool disposing) {
         if (disposing) {
           MyFont = null;
         }
       }
    
       public void Dispose() {
         Dispose(this);
    
         GC.SuppressFinalize(this); 
       } 
     }
    

    ....

     using (MyFontStorage storage = new MyFontStorage()) {
       ...
       // Storage is responsible for the font
       storage.MyFont = new Font(...);
       ...
       // Control has responsibility for the font as well, that's why
       // we have to create a copy in order to each font instance has one owner
       MyControl.Font = new Font(MyFontStorage.MyFont, MyFontStorage.Font.Style);  
       ... 
     }  
    

    Creating a copy instead of just assigning is a bad practice (prone to errors) and that's why you may want to implement a factory -

    "should I store the Fontname, size and style"

     public class MyFontFactory {
       private string m_FamilyName;
       private float m_Size;
       private FontStyle m_Style;
    
       ...
    
       public MyFontFactory(Font propotype) {
         ...
         m_FamilyName = propotype.FontFamily.Name;
         m_Size = propotype.Size;
         m_Style = propotype.Style;  
       } 
    
       public Font CreateFont() {
         return new Font(m_FamilyName, m_Size, m_Style);
       }
     } 
    

    ....

     MyFontFactory factory = new factory(SomeControl.Font);
     ...  
     // Much more natural:
     // MyFontFactory creates a new font and MyControl takes responsibility for it
     MyControl.Font = factory.CreateFont(); 
    

    Finally, in case of helper class / utility / routine etc.

     public class MyFontMisc {
       private Font m_MyFont;
    
       public Font MyFont {
         get {
           return m_MyFont; 
         } 
         set {
           m_MyFont = value;             
         }  
       }
    
       // Just some computations
       public float EmSizeInMillimeters {
         get {
           if (null == m_MyFont)
             return 0.0;
    
           ...
         }  
       }
     } 
    

    ......

     // MyFontMisc doesn't hold any responsibility for the font  
     MyFontMisc misc = new MyFontMisc(SomeControl.Font); 
    
     // MyFontMisc just uses font for some computation and doesn't take 
     // any responsibility for the font (which owns to SomeControl) 
     Length = misc.EmSizeInMillimeters * 3.0f + 15.0f;