4

In C#, I can write something like:

using (new MyDisposableClass().MethodA());

The semicolon causes a compiler warning to be shown which states possible mistaken empty statement. I haven't run the above code but won't the method still be called?

What uses is there of this type of coding convention? I saw another thread on here about this but I ask in case there areny differences now/therefore different replies.

Thanks

Gord Thompson
  • 116,920
  • 32
  • 215
  • 418
GurdeepS
  • 65,107
  • 109
  • 251
  • 387
  • what do you try to achieve with this clause? – zerkms May 19 '10 at 22:21
  • 1
    The point of using is that the clause defines the variable(s) and that the body is where you use said variable(s) to perform some actions. If you used the statement the way it was intended, you wouldn't be having this issue. – unholysampler May 19 '10 at 22:24
  • @unholysampler: not `variable`, but `reference` – zerkms May 19 '10 at 22:27
  • Here ; is used intentionally, you can use #pragma to turn off this warnings – bohdan_trotsenko May 19 '10 at 22:37
  • @unholysampler IMHO the point of `using` is that it defines a scope in which you use a disposable resource, and then automatically disposes it. You don't necessarily have to assign it to a variable, as demonstrated in ASP.NET MVC - `using (Html.BeginForm()) { ... }` (Instead of explicitly calling `Html.EndForm()`) – Daniel Schaffer May 20 '10 at 14:35
  • @zerkms: I meant object reference. I was just being lazy and using the terms interchangeably. @Daniel Schaffer: My point still holds for the `BeginForm` example because the method returns the disposable object and `Html.EndForm` is a helper method that calls the `EndForm` method of the object that gets called when it is disposed. – unholysampler May 20 '10 at 15:06

8 Answers8

11

this code basically translates to

MyDisposableClass tmp = new MyDisposableClass().MethodA();
try
{
}
finally
{
    if( tmp != null )
        tmp.Dispose();
}

Basically you're disposing the result of the call to MethodA, rather than disposing of the MyDisposableClass which is the likely intent.

The ; following the using statement is legal but the warning suggests that you might have added it there by mistake. For example the following code won't compile:

using( var tmp = new MyDisposableClass() );
{
    tmp.MethodA();
}

The parser evaluates two entirely separate blocks and is seen by the compiler as if you had typed this:

using( var tmp = new MyDispoableClass() )
{

}


{
    tmp.MethodA();
}

It's easy to miss a dangling ; by eye so the compiler warning is simply suggesting that you probably meant to do something else. There are times when the shorter concise statement is desired and I think the best way to indicate that it is on purpose is to use {} instead of a ;.

using( new MyDisposableClass().MethodA() ){}

Note still that this is disposing the result of the call to MethodA - not the MyDisposableClass instance. Your code should actually be written as

using( var tmp = new MyDisposableClass() ){ tmp.MethodA(); }
Paul Alexander
  • 31,970
  • 14
  • 96
  • 151
3

The using statement can be used as the opening for a clause, at the end which an instantied object is disposed of. In other words:

using (var foo = new bar())
{
  SomeStatments();
} 
//foo is disposed

or

using (var foo = new bar())
  SomeStatments();
//foo is disposed

Your semicolon isn't ending the using statement. It's actually ending an empty clause following the using statement. This is often not the programmers true intent. Thus, the compiler issues a "possibly mistaken empty statement" warning.

Update: Assuming the code you listed in the question is actual code, then you should probably turn MethodA into a static method, since you obviously are not enforcing a constraint or relying on any class members.

Abtin Forouzandeh
  • 5,635
  • 4
  • 25
  • 28
2

Why try to be clever?

This should be equivallent and future developers won't have to google what the briefer syntax might mean.

//By the name of the example, I can assume that MyDisposableClass 
//implements IDisposable
using (MyDisposableClass something = new MyDisposableClass())
{
   //Assuming the example code compiles, then the return value of MethodA
   //implemented IDisposable, too.
   using(something.MethodA())
   {

   };
}

And if you need to dispose of something after only one call, why not make MethodA do the clean up of what ever needs to be cleaned up?

MatthewMartin
  • 32,326
  • 33
  • 105
  • 164
  • 2
    Are you sure it's an equivalent? `using` expect references to objects as argument, but he passed the result of `MethodA` – zerkms May 19 '10 at 22:25
  • The example names confuse the matter. It looks like MyDisposable won't get disposed and the return value of MethodA() will be disposed. I'll update my code. – MatthewMartin May 20 '10 at 21:11
1

I think it would be clearer to write this:

using (var myDisposable = new MyDisposableClass())
{
   myDisposable.MethodA();
}

The way you have it, the result of MethodA would actually be getting treated as the IDisposable implementation.

Daniel Schaffer
  • 56,753
  • 31
  • 116
  • 165
  • 1
    And you know that is not the questioner's intent because...? – Abtin Forouzandeh May 19 '10 at 22:30
  • My assumption is based on the fact that the class he's instantiating is called `MyDisposableClass`. It could be that he wants to apply the using statement against the result of `MethodA`, but I suppose the larger issue is that the intent isn't clear. – Daniel Schaffer May 19 '10 at 22:35
0

You may be tempted to use this style. It does call the method. But it is an idiom at best, and is more likely to confuse the next reader - including you, in several months - than it is to enlighten.

Even replacing the ";" with an empty block (which eliminates the compiler warning) might lead to head-scratching when read later - and remember that code is read more often than it is written.

Paul Alexander's answer is correct, but I don't have sufficient reputation to comment on it.

I have used it on an occasion where I was just interested in the side effect of an exception being thrown from the method:

try {
    using (var _ = File.Open(logPath, FileMode.Open, FileAccess.Read)) { }
} catch (Exception ex) { ... }

File.Open returns a FileStream which must be closed or disposed. But I didn't really like it. I ended up naming the variable and putting an explicit Close in the block. I felt it would be easier to understand, later.

davidbak
  • 5,775
  • 3
  • 34
  • 50
0

Maybe helps this sample:

public static class Helper {
    public static void Using<T>( Action<T> action ) where T : IDisposable, new() {
        var obj = new T();
        action( obj );
    }
}

// ...
Helper.Using<MyDisposableClass>( cls => cls.MethodA() );
Helper.Using<OtherClass>( cls => {
    for( int i = 0; i < 5; i++ ) { cls.DoRandom(); }
} );
TcKs
  • 25,849
  • 11
  • 66
  • 104
-1

Sometimes compiler warnings are generated, then not cleaned up when you keep typing. Try building the solution, and see if it goes away.

Also, I'm not sure what comma you're referring to. Do you mean the semi-colon at the end of the line?

dlras2
  • 8,416
  • 7
  • 51
  • 90
-2

This method will essentially call MethodA() and then never use it. 'Using' uses whatever is in the parentheses only within that specific using block. Then it goes out of scope. So:

using (new MyDisposableClass().MethodA())
{
    //Code that uses MethodA()
}

...should not give that error, but MethodA() will still be inaccessible outside the using block.

Clarification:

You can still call new MyDisposableClass().MethodA() elsewhere in the program, but the specific call made within the code using (new MyDisposableClass().MethodA()) will go out of scope and be inaccessible.

Mike Webb
  • 8,855
  • 18
  • 78
  • 111
  • The using block is used to specify when you want an item that uses resources to be disposed. After the code in the using block is executed Dispose() is called on the object and the object essentially goes out of scope. If you type "using (a = new disposableObject()){}" then you will not be able to access 'a' anywhere else other than in the using block. If you declare it then not use it (i.e. "using (a = new disposableObject());") then the compiler will throw that warning. Maybe I did not explain this correctly, but I have the right idea in mind. The -2 I think is unnecessary. – Mike Webb May 20 '10 at 17:45
  • Here is an explanation of 'using': http://stackoverflow.com/questions/212198/what-is-the-c-using-block-and-why-should-i-use-it – Mike Webb May 20 '10 at 17:45
  • Oh, now I see my error. 'using (new MyDisposableClass().MethodA())' produces a warning because there is no object set to be used. Got it. – Mike Webb May 20 '10 at 17:48