Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# using statement more understanding

Tags:

c#

using

Can someone help me to understand following code

public Font MyFont { get; set; }

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

Is it valid to assign a disposing object to MyFont property?

like image 975
shyam_ Avatar asked Nov 19 '14 05:11

shyam_


2 Answers

Whilst it may be "valid to assign a disposed object to MyFont property", the object may no longer be useful because it may have released managed and/or unmanaged resources. Objects that are instantiated in the opening of a using statement indicate that the object's underlying class realises the IDisposable interface. This should be treated as a warning sign that when the object is disposed you should really stop interacting with it including keeping a reference to it.

In the case of a font, the font's underlying resources were disposed when you exited the using block:

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

This is easily proven if you attempt to use the font in any drawing operation.

This code will fail with a System.ArgumentException because the font is disposed:

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

The problem with your code is that you are allocating something in a using block and keeping a reference to it elsewhere. In your scenario because you want to use the font elsewhere it makes no sense to have a using block.

Bad:

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

Better:

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

Fonts I suspect make use of native fonts hence the resource.

like image 114
MickyD Avatar answered Oct 10 '22 19:10

MickyD


General rule of thumb: Don't use a disposable object outside the using block. Most of the time, disposable objects are unusable once disposed. If you follow this rule, you'll run into less trouble.

In this specific case, I wouldn't recommend using since you expect to use the font object outside the AssignFont method.

So, when do you dispose the font? One way is, you could dispose the font on the Disposed event of the parent control (assuming this is a control). However, unless you have thousands of fonts being generated during your application lifetime, you most like don't have to dispose the font at all. If you just have 5-10 fonts in the app, disposing them shouldn't be a big point of concern.

like image 25
Eren Ersönmez Avatar answered Oct 10 '22 20:10

Eren Ersönmez