【问题标题】:Should I dispose of an old font in the setter of a font property?我应该在字体属性的设置器中处理旧字体吗?
【发布时间】:2016-11-26 00:03:01
【问题描述】:

我有一个用于报表的设置对象,其中包含许多字体。

它们默认是这样的

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

但在用于报告的 gdi+ 呈现之前,它们可以在许多地方进行更改。这不在 winForms 控件中。

字体实现了 IDisposable,所以我应该在属性的 setter 中处理旧字体吗?或者我应该将字体名称、大小和样式存储为 3 个属性,并且只在需要时创建字体?

【问题讨论】:

  • @Jens 我不认为它是重复的,至少不是那个重复的。这不是 winforms 控件,我的对象负责字体
  • 如果它“对字体负责”,它应该Dispose它。如果它只是使用它(例如,如果你开发了一个辅助类或类似的例程)它不应该
  • @DmitryBychenko 您能否将其扩展为答案?我不应该为字体使用自动属性吗?
  • @dibs487:至于自动属性,这取决于:如果类负责字体,你绝对不应该;在 factory 的情况下你可以,但我认为你也不应该这样做:只写属性看起来违反直觉;编写字体 prototype 但读取 created 字体会将两个概念塞进一个属性中。至于辅助类,自动 Font 属性看起来相当不错。

标签: c# fonts


【解决方案1】:

这里的主要问题是这个类是否负责字体。 是的话,应该Dispose字体:

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

创建一个副本而不是仅仅分配是一个不好的做法(容易出错),这就是为什么你可能想要实现一个工厂 -

“我应该存储字体名称、大小和样式吗”

 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(); 

最后,在辅助类/实用程序/例程等的情况下。

 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 2020-04-23
    • 1970-01-01
    • 2012-01-22
    • 2021-09-11
    • 1970-01-01
    • 2012-05-26
    相关资源
    最近更新 更多