Reputation: 67243
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
Upvotes: 4
Views: 4545
Reputation: 6029
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.
Upvotes: 0
Reputation: 33173
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?
Upvotes: 2
Reputation: 26632
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(); }
} );
Upvotes: 0
Reputation: 5855
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.
Upvotes: 3
Reputation: 32377
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(); }
Upvotes: 11
Reputation: 57872
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.
Upvotes: 1
Reputation: 9003
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.
Upvotes: -2
Reputation: 8496
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?
Upvotes: -1