1

Following code generates a CA2000 warning:

Myclass myclass = null;
try
{
   myclass = new Myclass { Name = "a name" };
}
finally
{
   if (myclass != null)
   {
      myclass.Dispose();
   }
}

i found some topics with the same problem and as I understand the problem is, that the compiler generates for the constructor a temporary variable and for this variable I'm not calling Dispose().

var tmp = new MyClass();
tmp.Name = "a name";
myclass = tmp:

so my question is, if there is a solution with using object initializer which not generates a ca2000 warning.

thanks in advanced.

Steven
  • 166,672
  • 24
  • 332
  • 435
rhe1980
  • 1,557
  • 1
  • 15
  • 36
  • I also wondered why you were manually writing out a `using` statement, but the same warning is generated even there. – Damien_The_Unbeliever Jan 05 '12 at 07:42
  • See also [this question](http://stackoverflow.com/questions/6409918/object-initializer-and-dispose-when-property-can-throw-exception) – Damien_The_Unbeliever Jan 05 '12 at 07:46
  • I saw this topic (and some others with same problem). but in all this topics I didn't found a solution with using object initializers. – rhe1980 Jan 05 '12 at 07:56
  • 2
    That's because all of the answers boil down to "there's no way to do it, because the way that object initializers are implemented mean that you could leak the `IDisposable` object." – Damien_The_Unbeliever Jan 05 '12 at 07:58

1 Answers1

1

As Damien points out in the comments, the FxCop warning is valid, since the C# compiler creates the IDisposable instance in a hidden temp variable, and when an exception is thrown during the initialization of one of the properties that instance will not get disposed.

With a good API design this would not be a problem, since resources (things that implement IDisposable) should contain an Open (or Begin, Start, whatever) method (according to the Framework Design Guidelines), and should not leak before Open is called. This rule is created for the same reason as what you are experiencing: to prevent leaking during initialization. The FDG were written before C# 3.0, but the same problem exists when the an exception is thrown from within the constructor of that instance (which can always happen because of asynchronous exceptions such as thread aborts). Since the reference to the instance isn't published at that point, there is no way for anyone to dispose that instance. Initializing the underlying resources during construction is therefore not advised.

So you can safely discard that warning when Myclass contains some sort of Open method, and when you're not initializing it with values that implement IDisposable themselves. In other cases, you should revert to the following:

var myclass = new MyClass();

try
{
    myclass.Name = "a name";
}
finally
{
    myclass.Dispose();
}
Steven
  • 166,672
  • 24
  • 332
  • 435