13

I am returning the variable I am creating in a using statement inside the using statement (sounds funny):

public DataTable foo ()
{
    using (DataTable properties = new DataTable())
    {
       // do something
       return properties;
    }
}

Will this Dispose the properties variable??

After doing this am still getting this Warning:

Warning 34 CA2000 : Microsoft.Reliability : In method 'test.test', call System.IDisposable.Dispose on object 'properties' before all references to it are out of scope.

Any Ideas?

Thanks

1
  • 3
    Regardless, this is just bad design and should be reworked. Commented May 12, 2010 at 20:56

7 Answers 7

13

If you want to return it, you can't wrap it in a using statement, because once you leave the braces, it goes out of scope and gets disposed.

You will have to instantiate it like this:

public DataTable Foo() 
{ 
    DataTable properties = new DataTable();
    return properties; 
} 

and call Dispose() on it later.

Sign up to request clarification or add additional context in comments.

1 Comment

It feels like foo() == GetUsefulDataTable() and the using block should be what calls this function.
12

Yes, it will dispose it - and then return it. This is almost always a bad thing to do.

In fact for DataTable, Dispose almost never does anything (the exception being if it's remoted somewhere, IIRC) but it's still a generally bad idea. Normally you should regard disposed objects as being unusable.

3 Comments

So, what would be the correct pattern for returning a IDisposable object from a method without triggering CA2000 warning?
@Jhonny: I don't know, to be honest - I haven't used code analysis like this. I'd expect there'd be some way to suppress the warning.
@JhonnyD.Cano-Leftware- If you are going to instantiate and return IDisposable things you need to explicitly dispose them in your code. Your code analysis "should" pick up that you dispose this elsewhere manually.
7

Supposedly, this is the pattern for a factory method that creates a disposable object. But, I've still seen Code Analysis complain about this, too:

        Wrapper tempWrapper = null;
        Wrapper wrapper = null;

        try
        {
            tempWrapper = new Wrapper(callback);
            Initialize(tempWrapper);

            wrapper = tempWrapper;
            tempWrapper = null;
        }
        finally
        {
            if (tempWrapper != null)
                tempWrapper.Dispose();
        }

        return wrapper;

This should guarantee that if the initialization fails, the object is properly disposed, but if everything succeeds, an undisposed instance is returned from the method.

MSDN Article: CA2000: Dispose objects before losing scope.

3 Comments

Isn't this basically equivalent to a catch block? Why wouldn't you write Wrapper x = null; try { ... } catch { if (x != null) x.Dispose(); }. The intent is not only 100% more obvious, but avoids the unnecessary temp variable and manual cleanup.
I don't disagree. But I just looked this up recently myself, not because I was worried about disposing the object on failure, but because I was trying to find the code pattern that would eliminate the CA2000 warning without me having to suppress it via attribute. The code analysis process specifically checks to see if the object is disposed in a finally block due to the nature of the rule being enforced. I perceive that this question is really about CA2000, not about disposing objects.
@Juliet: The catch statement is missing a rethrow, and even with a rethrow the semantics aren't the same as not having a catch. Among other things, if the try block contains to calls to some method blah which could cause an exception, catch-and-rethrow will cause the stack trace to show the line number of the rethrow rather than the the call to blah (the stack trace within blah will be correct, but the line number for the call won't be).
3

Yes. Why are you using the using keyword on something you don't want disposed at the end of the code block?

The purpose of the using keyword is to dispose of the object.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Comments

2

The point of a using block is to create an artificial scope for a value/object. When the using block completes, the object is cleaned up because it is no longer needed. If you really want to return the object you are creating, than it is not a case where you want to use using.

This will work just fine.

public DataTable foo ()
{
    DataTable properties = new DataTable();
    // do something
    return properties;
}

Comments

1

Your code using the using keyword expands to:

{
    DataTable properties = new DataTable();
    try
    {
        //do something
        return properties;
    }
    finally
    {
        if(properties != null)
        {
            ((IDisposable)properties).Dispose();
        }
    }
}

Your variable is being disposed by nature of how using works. If you want to be able to return properties, don't wrap it in a using block.

Comments

0

The other responses are correct: as soon as you exit the using block, your object is disposed. The using block is great for making sure that an object gets disposed in a timely manner, so if you don't want to rely on the consumers of your function to remember to dispose the object later, you can try something like this:

public void UsingDataContext (Action<DataContext> action)
{
    using (DataContext ctx = new DataContext())
    {
       action(ctx)
    }
}

This way you can say something like:

var user = GetNewUserInfo();
UsingDataContext(c => c.UserSet.Add(user));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.