7
votes

When I run code analysis tool I get the following:

Warning 1 CA2000 : Microsoft.Reliability : In method 'Class1.test.testMethod()', object 'dt' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'dt' before all references to it are out of scope. How to resolve the warnings??

public void testMethod()
{
   DataTable dt = new DataTable();
   DataTable dt1= new DataTable();
      try
      {
         if (dt.Rows.Count == 0)
         {
            dt1.Merge(dt);
         }
      }
      catch
      {
         throw;
      }
      finally
      {
         if (dt != null) dt.Dispose();
         if (dt1 != null) dt1.Dispose();
      }
}
8
object 'dt' is not disposed along all exception paths I think the compiler is actually complaining about the empty catch block, but using a using statement (like the currently top rated answer) should be the best practice as you don't even need to call dispose then. EDIT: +1 for being bothered about warnings. - Izzy

8 Answers

5
votes

Not really sure why you are getting that error, but you can try using statement block in your method and see if the error goes away. Try it like:

public void testMethod()
{
    using (DataTable dt = new DataTable())
    using (DataView dv = new DataView(dt))
    {
        //your work
    }
}
2
votes

From Dispose objects before losing scope

If a disposable object is not explicitly disposed before all references to it are out of scope, the object will be disposed at some indeterminate time when the garbage collector runs the finalizer of the object. Because an exceptional event might occur that will prevent the finalizer of the object from running, the object should be explicitly disposed instead.

To fix a violation of this rule, call System.IDisposable.Dispose on the object before all references to it are out of scope.

Note that you can use the using statement (Using in Visual Basic) to wrap objects that implement IDisposable. Objects wrapped in this manner will automatically be disposed at the close of the using block.

using (DataTable dt = new DataTable())
using (DataView dv = new DataView(dt))
{

}
2
votes

In the 7th line in your code you have created a dummy DataTable that is not used. The compiler is complaining about that DataTable and DataView objects. Change the code like below and it will work.

public class Class1
{
    public class test
    {
        public void testMethod()
        {
            DataTable dt = null;
            DataView dv = null;


         try
        {
            // dt must be assigned a value only within the try block
            dt = new DataTable(dt);
            dv = new DataView(dt);
         }
        catch
        { }
        finally
        {
            if (dt != null) dt.Dispose();
            if (dv != null) dv.Dispose();

         }
        }
    }
}

Update

if you dispose both dt and dv you will get CA2202 error. This is because dt is being disposed twice. Once while disposing dt and once while disposing dv. To avoid that you must assign null to dt at the end of the try/catch block.

    try
    {
        dt = new DataTable(dt);
        dv = new DataView(dt);
        dt=null;
     }
1
votes

I suspect the error is happening because you are creating two DataViews, and only one of them will ever be disposed: you initialise dv to a new DataView and then assign another in the try block. The one from the initial assignment won't be disposed when you hit the finally, because you'll have no reference to it.

Modify your declaration DataView dv = new DataView () to just declare the variable, and not initialise it:

public void testMethod()
{
    DataTable dt = new DataTable();
    DataView dv = null;

    try
    {
        dv = new DataView(dt);
    }
    finally
    {
        if (dt != null) dt.Dispose();
        if (dv != null) dv.Dispose();
    }
}

NOTE: This directly fixes your second error message (about dv), and indirectly addresses the first (about dt). The first error is raised because, if the redundant initialisation of dv were to throw an exception, dt would not be disposed - so removing that initialisation fixes the error.

1
votes

Exactly what your example code is demonstrating is unclear.

However, if you are trying to clear a false positive on CA2000 when following the MSDN recommended pattern, then there are some known remedies. I outline two cases here where a simple code change enables Code Analysis to recognize the recommended pattern:

  1. The temporary must be named as the string "temp" prepended in camelCase to the ultimate destination IDisposable.
  2. The ultimate destination IDisposable must be the return value of a function.
0
votes

Probably because the DataTable initializer theoretically might break before dispose. You may try to initialize it initially with null and inside the try block with a new DataTable instance. You have the nullable test in finally after all.

Something like

public class Class1
{
    public class test
    {
        public void testMethod()
        {
            DataTable dt = null;

         try
        {
            dt = new DataTable();

         }
        catch
        { }
        finally
        {
            if (dt != null) dt.Dispose();
         }
    }
    }
}
0
votes

Occurs because you are initializing dt outside of the try block.

public void testMethod()
{
    DataTable dt = null;
    DataView dv = null;
    try
    {
        dt = new DataTable();
        dv = new DataView(dt);
    }
    catch
    {
    }
    finally
    {
        if (dt != null) dt.Dispose();
        if (dv != null) dv.Dispose();
    }
}

}

As stated in other answers you can also use using blocks instead of try...finally.

public void testMethod()
{
    using (DataTable dt = new DataTable())
    {
        using (DataTable dv = new DataView(dt))
        {
        }
    }
}

One question: was it your intention to make the test class a nested class of Class1?

0
votes
   public class test
    {
        public void testMethod()
        {
            DataTable dt = null;
            DataView dv = null;


         try
        {
           dv = new DataView(dt);
         }
        catch
        { }
        finally
        {
            if (dt != null) dt.Dispose();
            if (dv != null) dv.Dispose();

         }
        }
    }
}