views:

245

answers:

7

If I am using the using keyword, do I still have to implement IDisposable?

+5  A: 

You are confusing things. You can only use the "using" keyword on something that implements IDisposable.

Edit: If you use the using keyword, you don't have to explicity invoke Dispose, it will be called automatically at the end of the using block. Others have already posted examples of how the using statement is translated into a try - finally statement, with Dispose invoked within the finally block.

Richard Hein
You can using "using" keyword when reading data from a recordset, correct?
Troy
@Troy, yes, that's because IDataReader implements IDisposable.
Tim Jarvis
Only if whatever is wrapping your recordset implements IDisposable. If it compiles then it implements IDisposable....
Richard Hein
+2  A: 

Using will only dispose of disposable objects. So wraping a using block around an object that does not implement IDisposable is rather useless will in fact cause a compiler error.

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

As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

brendan
In fact, it is a compiler error.
Timwi
+11  A: 

If you use the using statement the enclosed type must already implement IDisposable otherwise the compiler will issue an error. So consider IDisposable implementation to be a prerequisite of using.

If you want to use the using statement on your custom class, then you must implement IDisposable for it. However this is kind of backward to do because there's no sense to do so for the sake of it. Only if you have something to dispose of like an unmanaged resource should you implement it.

// To implement it in C#:
class MyClass : IDisposable {

    // other members in you class 

    public void Dispose() {
        // in its simplest form, but see MSDN documentation linked above
    }
}

This enables you to:

using (MyClass mc = new MyClass()) {

    // do some stuff with the instance...
    mc.DoThis();  //all fake method calls for example
    mc.DoThat();

}  // Here the .Dispose method will be automatically called.

Effectively that's the same as writing:

MyClass mc = new MyClass();
try { 
    // do some stuff with the instance...
    mc.DoThis();  //all fake method calls for example
    mc.DoThat();
}
finally { // always runs
    mc.Dispose();  // Manual call. 
}
John K
Can you show a code example, plz?
Troy
@Troy: Example added to highlight explanation.
John K
@jdk Actually its quite a useful pattern for whenever you have "sandwich" code that must / should execute some stuff in a finally section. For example a common scenario would be a busy cursor, the steps are...1./ Copy the existing cursor2./ set the cursor to your wait cursor3./ in a finally section copy back the original.With a using and IDisposable you could then write code something likeusing(Busy.WaitCursor){ //Where WaitCursor is a static property that returns an Instance of Busy the constructor copies and sets and the dispose() re-sets.}
Tim Jarvis
@Tim - another good example is changing the colors of a console application (I think I saw that on Wes Dyer's blog). For tasks like that it's sometimes useful to implement a Disposable class that simply wraps an Action which gets executed on Dispose(). However, I can't help but feel that it's a bit of an anti-pattern sometimes. I wonder how others feel on the topic of a generic Disposable class.
Alex Humphrey
+9  A: 

You can't have one without the other.

When you write :

using(MyClass myObj = new MyClass())
{
    myObj.SomeMthod(...);
}

Compiler will generate something like this :

MyClass myObj = null;
try
{
    myObj = new MyClass();
    myObj.SomeMthod(...);
}
finally
{
    if(myObj != null)
    {
        ((IDisposable)myObj).Dispose();
    }
} 

So as you can see while having using keyword it is assumed/required that IDisposable is implemented.

Incognito
+1, but not assumed - required. The compiler code you showed here would except with an invalid cast exception if the type didn't implement IDisposable. This is why the compiler protects this from happening by giving a compile time error making IDisposable required, not assumed, for use in a using.
Jimmy Hoffa
@Jimmy yes you are right, saying assumed I meant that. Answer is updated.
Incognito
+2  A: 

Yes, the using keyword is syntactic sugar for this type of pattern...(from msdn)

  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }

Edit: a useful example.

When you find you are doing things in a finally section consistantly, for example resetting a Cursor back to its default after having set it to a wait cursor, this is a candidate for this pattern...

  public class Busy : IDisposable
  {

    private Cursor _oldCursor;

    private Busy()
    {
      _oldCursor = Cursor.Current;
    }

    public static Busy WaitCursor
    {
      get
      {
        Cursor.Current = Cursors.WaitCursor;
        return new Busy();
      }
    }

    #region IDisposable Members

    public void Dispose()
    {
      Cursor.Current = _oldCursor;
    }

    #endregion
  }

Called like...

using(Busy.WaitCursor)
{
  // some operation that needs a wait cursor.
}
Tim Jarvis
+1  A: 

The using keyword already implements, so if you use the using keyword, you do not have to invoke IDisposable

user279521
+1  A: 

You must implement IDisposable to use using. If you try to use using() on a type that does not implement IDisposable you get the following compile time error:

error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable'
Jimmy Hoffa