Mike159 Mike159 - 3 months ago 13
C# Question

Dispose not being called correctly on disposable object

I have a function which draws a list of objects onto a bitmap to create a crude map. Code analysis throws a warning (CA2000) which says the object 'drawPen' isn't disposed along all exception paths. As far as I can see it is disposed at the end of the function and there is no inaccessible code where it could be missed.

Does anyone know why the compiler thinks it is not being disposed of properly?

public void drawUpdates(List<areaObjects> objectLocations)
{
Rectangle areaToClone = new Rectangle(0, 0, writeOnceMap.Width, writeOnceMap.Height);
var pixelFormat = writeOnceMap.PixelFormat;
areaBitMap = writeOnceMap.Clone(areaToClone, pixelFormat);
Pen drawPen = new Pen(Color.Black, 2);
drawPen.Width = 2;
foreach(areaObjectsop2d in objectLocations)
{
int xPosition = (int)(op2d.XYZ.xPos * mapScale);
int yPosition = (int)(op2d.XYZ.yPos * mapScale);
Point[] crossMarker = getCrossShape(xPosition, yPosition);

using (var graphics = Graphics.FromImage(areaBitMap))
{
graphics.DrawPolygon(drawPen, crossMarker);
}
}
drawPen.Dispose();
}

Answer

You get the warning because in the case of an exception in your function the drawPen will not be disposed.

You can wrapp your code in a try finally and in the finally call the .Dispose() or better - use the using which does precisely that.

public void drawUpdates(List<areaObjects> objectLocations)
{
    Rectangle areaToClone = new Rectangle(0, 0, writeOnceMap.Width, writeOnceMap.Height);
    var pixelFormat = writeOnceMap.PixelFormat;
    areaBitMap = writeOnceMap.Clone(areaToClone, pixelFormat);
    using(Pen drawPen = new Pen(Color.Black, 2))
    {
        foreach(areaObjectsop2d in objectLocations)
        {
            int xPosition = (int)(op2d.XYZ.xPos * mapScale);
            int yPosition = (int)(op2d.XYZ.yPos * mapScale);
            Point[] crossMarker = getCrossShape(xPosition, yPosition);

            using (var graphics = Graphics.FromImage(areaBitMap))
            {
                graphics.DrawPolygon(drawPen, crossMarker);
            }
        }
    }
}

The above is equivalent to:

Pen drawPen = new Pen(Color.Black, 2);
try
{
    /*Your code*/
}
finally
{
    drawPen.Dispose();
}