views:

230

answers:

8

I need to force the use of "using" to dispose a new instance of a class.

public class MyClass : IDisposable
{
   ...
}

using(MyClass obj = new MyClass()) // Force to use "using"
{
}
A: 

No, you cannot do that. You can't even force them to call dispose. The best you can do is add a finalizer. Just keep in mind that the finalizer will get called when the object is disposed and that is up to the runtime.

Tom Cabanski
A: 

No it is not possible. Now what you can do is call the dispose method in the finalizer of the class (and then you can suppress the use of it if they do actually call the dispose method). That way it will fire if not done explicitly in code.

This link will show you how to implement the finalizer / dispose pattern:

http://www.devx.com/dotnet/Article/33167

Kevin
+1  A: 

If you want force to use using on this class, your code to support this class you might code in other class and hide MyClass for normal use.

Svisstack
This wouldn't work because your "wrapper" class would have to implement IDisposable to allow you to dispose of the original class and you're back at square one, using a finalizer.
juharr
No, the wrapper class may not implement IDisposable is not metter, he control Disposing of MyClass. Yes the wrapper dispose is to dispose her children element (eg. MyClass), but he can dispose MyClass after he end works, and Wrapper class can live along time ago this operation.
Svisstack
+2  A: 

I wonder if FXCop could enforce that rule?

Matthew Sposato
Yes, there is the DisposeObjectsBeforeLosingScope rule. See: http://blogs.msdn.com/codeanalysis/archive/2010/03/22/what-s-new-in-code-analysis-for-visual-studio-2010.aspx
LBushkin
+3  A: 

The using statement is a shorthand that the compiler converts from:

(using DisposableObject d = new DisposableObject()){}

into:

DisposableObject d = new DisposableObject()
try
{

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

so you are more or less asking if it is possible to enforce writing a try/finally block that calls Dispose for an object.

panamack
*Technically*, it would be `((IDisposable)d).Dispose();` ;)
Anthony Pegram
Ok I'll try to remember that :)
panamack
@panamack: There actually *is* a difference between them. See http://blogs.msdn.com/mhop/archive/2006/12/12/implicit-and-explicit-interface-implementations.aspx for discussion of implicit vs explicit interface implementation, which includes examples where casting to the interface matters.
Brian
@Brian, thanks for the link. so it's (IDisposable)d because if Dispose() is explicitly implemented it may be hidden from d unless cast to the interface.
panamack
@panamack: And the code might still compile, since there may be an implicit implementation of Dispose, too.
Brian
+12  A: 

The fact that you need to ensure that the object is disposed indicates a design flaw. It's fine if disposing is the polite or efficient thing to do, but it should not be semantically necessary.

There is no way to enforce that an object is disposed of via the using statement. However, what you can do is maintain a flag in the object that indicates whether the object was disposed or not, and then write a finalizer that checks that flag. If the finalizer detects that the object wasn't disposed, then you can have the finalizer, say, terminate the process via failfast. That is, so severely punish the user who neglected to dispose the object that they are forced to either fix their bug or stop using your object.

That doesn't strike me as nice, good, or polite, but you're the only one who knows what the terrible, terrible consequences are of failing to dispose the object. Whether applying a punishment to people who fail to follow your crazy rules is better than living with the consequences of them failing to follow the rules is for you to decide.

Eric Lippert
@Eric: It's a funny coincidence, but I posted a similar question to your blog about this topic earlier today. One comment I would make is that disposal becomes semantically necessary when dealing with very limited resources whose consumption can adversly affect an entire process. It would be helpful if the compiler could enforce (or at least warn) when certain disposable resources are not deterministically released - for this purpose I suggested an attribute (RequiresRAIISemantics, or the like) that could be tagged on types implementing IDisposable.
LBushkin
+3  A: 

It's ugly, but you could do something like this:

    public sealed class DisposableClass : IDisposable
    {
        private DisposableClass()
        {

        }

        public void Dispose()
        {
            //Dispose...
        }

        public static void DoSomething(Action<DisposableClass> doSomething)
        {
            using (var disposable = new DisposableClass())
            {
                doSomething(disposable);
            }
        }
    }
Dan Bryant
This is a very interesting use of continuation passing style (CPS), but I don't know if it could really be extensible to the general case of acquiring and releasing resources.
LBushkin
A: 

You should look into RAII, which is a technique that ensures that the acquired resources will be properly disposed.

What I mean is that if you can't force the Dispose method to be called (through using or directly), you can put its content inside another method that will be called, such as the destructor.

It is a common pattern to implement IDisposable as below:

// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
    Dispose(true);
    // This object will be cleaned up by the Dispose method.
    // Therefore, you should call GC.SupressFinalize to
    // take this object off the finalization queue 
    // and prevent finalization code for this object
    // from executing a second time.
    GC.SuppressFinalize(this);
}

// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the 
// runtime from inside the finalizer and you should not reference 
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
    // Check to see if Dispose has already been called.
    if(!this.disposed)
    {
        // If disposing equals true, dispose all managed 
        // and unmanaged resources.
        if(disposing)
        {
            // Dispose managed resources.
            component.Dispose();
        }

        // Call the appropriate methods to clean up 
        // unmanaged resources here.
        // If disposing is false, 
        // only the following code is executed.

        // TODO: write code
    }
    disposed = true;         
}

// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method 
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~ClassName()
{
    // Do not re-create Dispose clean-up code here.
    // Calling Dispose(false) is optimal in terms of
    // readability and maintainability.
    Dispose(false);
}

Source: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

Jader Dias