C#使用语句更加了解

时间:2014-11-19 05:24:51

标签: c# using

有人可以帮助我理解以下代码

public Font MyFont { get; set; }

void AssignFont()
{
    using (Font f = new Font("Shyam",2))
    {
        this.MyFont = f;
    }
}

将处置对象分配给MyFont属性是否有效?

2 个答案:

答案 0 :(得分:9)

虽然将处置对象分配给MyFont属性可能“有效”,但该对象可能不再有用,因为它可能已释放托管和/或非托管资源。在using语句的开头实例化的对象表明该对象的底层类实现了IDisposable接口。这应该被视为一个警告标志,当对象处置时,你应该真的停止与它进行交互,包括保持对它的引用。

如果是字体,退出使用块时会处理字体的基础资源:

using (Font f = new Font("Shyam",2))
{
    this.MyFont = f;
}

如果您尝试在任何绘图操作中使用该字体,则可以很容易地证明这一点。

此代码将失败并显示System.ArgumentException,因为字体已被处理:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void UserControl1_Load(object sender, EventArgs e)
    {
        if (DesignMode)
        {
            return;
        }

        AssignFont();
    }

    #region Overrides of Control

    /// <summary>
    /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
    /// </summary>
    /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data. </param>
    protected override void OnPaint(PaintEventArgs e)
    {
        try
        {
            var g = e.Graphics;

            g.FillRectangle(Brushes.White, e.ClipRectangle);

            g.DrawString("Hi there", MyFont, Brushes.Black, 0, 0); // <--- this will fail
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.Message);
        }
    }

    #endregion

    void AssignFont()
    {
        using (Font f = new Font("Shyam", 2))
        {
            this.MyFont = f;
        } // <---- MyFont now points to a disposed object
    }

    public Font MyFont { get; set; }
}

enter image description here

您的代码的问题在于您正在使用块中分配某些内容并在其他位置保留对它的引用。在您的方案中,因为您想在其他地方使用该字体,所以有一个using块是没有意义的。

为:

using (Font f = new Font("Shyam",2))
{
    this.MyFont = f;
}

更好:

this.MyFont = new Font("Shyam",2)

字体我怀疑使用本机字体,因此资源。

答案 1 :(得分:4)

一般经验法则:不要在using块之外使用一次性物品。大多数情况下,一次性物体一旦处理就无法使用。如果你遵守这条规则,你就会遇到麻烦。

在这种特定情况下,我不推荐使用using,因为您希望使用AssignFont方法之外的字体对象。

那么,你什么时候处理这​​个字体?一种方法是,您可以在父控件的Disposed事件上处理该字体(假设this是一个控件)。但是,除非您在应用程序生命周期内生成了数千种字体,否则您最喜欢必须处理该字体。如果你在应用程序中只有5-10个字体,处理它们应该不是一个值得关注的问题。