What does this statement means in C#?
using (object obj = new object())
{
//random stuff
}
It means that obj implements IDisposible and will be properly disposed of after the using block. It's functionally the same as:
{
//Assumes SomeObject implements IDisposable
SomeObject obj = new SomeObject();
try
{
// Do more stuff here.
}
finally
{
if (obj != null)
{
((IDisposable)obj).Dispose();
}
}
}
using (object obj = new object())
{
//random stuff
}
Is equivalent to:
object obj = new object();
try
{
// random stuff
}
finally {
((IDisposable)obj).Dispose();
}
why does it exist tho.
It exists for classes where you care about their lifetime, in particular where the class wraps a resource in the OS and you want to release it immediately. Otherwise you would have to wait for the CLR's (non deterministic) finalizers.
Examples, file handles, DB connections, socket connections, ....
it is a way to scope an object so the dispose method is called on exit. It is very useful for database connections in particuler. a compile time error will occur if the object does not implement idisposable
using ensures the allocated object is properly disposed after the using block, even when an unhandled exception occurs in the block.
Related
The MSDN recommends putting any instantiation of classes that implement IDisposable into a using block. Or alternatively, if it is being instantiated within a try-catch block, then Dispose in Finally.
Are there any problems with using a using block within a try-catch block like so?
try
{
using (Foo bar = new Foo())
{
bar.doStuff();
}
}
catch (Exception e)
{
//vomit e
}
Of course I can just call Dispose in a Finally block, but I'm a newbie to programming and I'm just curious to know if doing something like this is practically acceptable or if someone would smack me up the back of my head and yell at me that I'm Doing-It-Wrong™.
Or rather, I'm more interested in knowing why this would be wrong if it is.
No, that looks perfectly fine. Your bar instance will be disposed before you even get into the catch block.
This is... drum roll... absolutely fine.
The only issue is that you shouldn't use catch (Exception), but catch the specific errors you're interested in (even if this is just an example), but that has no bearing on the using. In fact, the only reason why you would put the using outside the try block is because you want to continue doing something with bar that's unrelated to the code that failed -- otherwise, keeping the scope as small as possible is generally a good idea.
It is OK but you lost access to object that would have caused the exception in the exception.
And catching general exceptions is not considered a good practice
Foo bar = null;
try
{
bar = new Foo();
bar.doStuff();
}
catch (IndexOutOfRangeException e)
{
//vomit e
Debug.WriteLine(e.msg);
if(bar == null)
Debug.WriteLine("bar = new Foo() failed ");
else
Debug.WriteLine("bar fail ID = " + bar.ID);
}
catch (Exception e)
{
// ...
// unless you are going to handle it gracefully you should rethrow it
}
finally
{
if(bar != null) bar.Dispose();
}
Your example code is redundant. The Using() documentation states:
A using statement of the form
using (ResourceType resource = expression)
statement corresponds to one of two possible expansions. When ResourceType is a value type, the expansion is
{
ResourceType resource = expression;
try {
statement;
}
finally {
((IDisposable)resource).Dispose();
}
}
Otherwise, when ResourceType is a reference type, the expansion is
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}
In either expansion, the resource variable is read-only in the embedded statement.
Your code will ultimately look something like:
try
{
Foo bar = new Foo()
try
{
bar.doStuff();
}
finally
{
if (bar != null) ((IDisposable)bar).Dispose();
}
}
catch (Exception e)
{
//vomit e
}
No real reason for two try statements. It's not wrong code, it's just redundant in the context of multiple try statements. You question appears to be about Disposing of an object. In this context, it is redundant. If you are also concerned about the object constructor throwing an exception, the obviously this would be needed.
Are there any problems with using a using block within a try-catch block like so?
No, I write your example all the time.
Of course I can just call Dispose in a Finally block,
Sort of, the constructor must be called outside the try/catch, otherwise the variable will be out of scope by the time you reach the finally block
valid:
var foo = new bar();
try
{
}
finally
{
foo.Dispose();
}
invalid:
try
{
var foo = new bar();
}
finally
{
foo.Dispose();
}
No, it is fine, but if you want to access bar during the catch, you'll need an inner try catch:
try
{
using (Foo bar = new Foo())
{
try
{
bar.doStuff();
}
catch (Exception e)
{
//vomit e, with bar available.
}
}
}
catch (Exception e)
{
//vomit e, relating to a problem during creation of Foo.
}
or, as suggested in the comments, factor out the inner block into a new method.
So i am currently disposing many objects when i close my form. Even though it probably disposes it automatically. But still i prefer to follow the "rules" in disposing, hopefully it will stick and help prevent mistakes.
So here is how i currently dispose, which works.
if (connect == true)
{
Waloop.Dispose();
connect = false;
UninitializeCall();
DropCall();
}
if (KeySend.Checked || KeyReceive.Checked)
{
m_mouseListener.Dispose();
k_listener.Dispose();
}
if (NAudio.Wave.AsioOut.isSupported())
{
Aut.Dispose();
}
if (Wasout != null)
{
Wasout.Dispose();
}
if (SendStream != null)
{
SendStream.Dispose();
}
So basically, the first is if a bool is true, meaning if it isn´t those can be ignore, as they haven´t been made i think.
The others are just ways for me to dispose if it´s there. but it´s not a very good way, i would like to have it in 1 big function, meaning.
Dispose if it´s NOT disposed. or something.
I know that many of them has the "isdisposed" bool, so it should be possible if i can check every object, and dispose if it´s false.
How about a helper method which takes objects which implement IDisposable as params?
void DisposeAll(params IDisposable[] disposables)
{
foreach (IDisposable id in disposables)
{
if (id != null) id.Dispose();
}
}
When you want to dispose multiple objects, call the method with whatever objects you want to dispose.
this.DisposeAll(Wasout, SendStream, m_mouseListener, k_listener);
If you want to avoid calling them explicity, then store them all in a List<>:
private List<IDisposable> _disposables;
void DisposeAll() {
foreach(IDisposable id in _disposables) {
if(id != null) id.Dispose();
}
}
You can implement a Disposer class, that will do the work for you, along these lines:
public class Disposer
{
private List<IDisposable> disposables = new List<IDisposable>();
public void Register(IDisposable item)
{
disposables.Add(item);
}
public void Unregister(IDisposable item)
{
disposables.Remove(item);
}
public void DisposeAll()
{
foreach (IDisposable item in disposables)
{
item.Dispose();
}
disposables.Clear();
}
}
Then, instead of the ugly code in your main class, you can have something like:
public class Main
{
//member field
private Disposer m_disposer;
//constructor
public Main()
{
....
m_disposer = new Disposer();
//register any available disposables
disposer.Register(m_mouseListener);
disposer.Register(k_listener);
}
...
public bool Connect()
{
...
if (isConnected)
{
Waloop = ...
Wasout = ...
// register additional disposables as they are created
disposer.Register(Waloop);
disposer.Register(Wasout);
}
}
...
public void Close()
{
//disposal
disposer.DisposeAll();
}
}
I suggest you use the using statement. So with your code, it would look something like this:
using (WaloopClass Waloop = new WaloopClass())
{
// Some other code here I know nothing about.
connect = false; // Testing the current value of connect is redundant.
UninitializeCall();
DropCall();
}
Note there is now no need to explicitly Dispose Waloop, as it happens automatically at the end of the using statement.
This will help to structure your code, and makes the scope of the Waloop much clearer.
I am going to suppose that the only problem you’re trying to solve is how to write the following in a nicer way:
if (Wasout != null)
Wasout.Dispose();
if (SendStream != null)
SendStream.Dispose();
This is a lot of logic already implemented by the using keyword. using checks that the variable is not null before calling Dispose() for you. Also, using guarantees that thrown exceptions (perhap by Wasout.Dispose()) will not interrupt the attempts to call Dispose() on the other listed objects (such as SendStream). It seems that using was intended to allow management of resources based on scoping rules: using using as an alternative way to write o.Dispose() may be considered an abuse of the language. However, the benefits of using’s behavior and the concision it enables are quite valuable. Thus, I recommend to replace such mass statically-written batches of the “if (o != null) o.Dispose()” with an “empty” using:
using (
IDisposable _Wasout = Wasout,
_SendStream = SendStream)
{}
Note that the order that Dispose() is called in is in reverse of how objects are listed in the using block. This follows the pattern of cleaning up objects in reverse of their instantiation order. (The idea is that an object instantiated later may refer to an object instantiated earlier. E.g., if you are using a ladder to climb a house, you might want to keep the ladder around so that you can climb back down before putting it away—the ladder gets instantiated first and cleaned up last. Uhm, analogies… but, basically, the above is shorthand for nested using. And the unlike objects can be smashed into the same using block by writing the using in terms of IDisposable.)
dotnetfiddle of using managing exceptions.
I wonder if the object created in the usingstatement gets disposed if I perform a return or throw operation. Example as follows.
using(SomeClass thing = new SomeClass())
{
...
if(condition)
return;
...
}
Will the above get confused or is GC to be trusted here?
Yes, it will. The using statement will result in a finally block being created. A finally block's code will be run even if an exception is thrown in the related try block, or if there is a return statement in that try block.
There are only a few exceptions that can cause a finally block's code to not be executed, and they are all listed here, but my guess is that in your situation you'll be able to live with those consequences.
using is the equivalent of try-finally so, yes, it does.
dispose if it is implemented will always get called. Its the equivalent of calling dispose in a finally block.
It will dispose, yes. It will create a finally block in the CIL code.
Yes, because using is extended into a try finally by the compiler. The dispose will occur inside the finally block. Also, the finally will contain a test to check if the variables in the using are null (in case there are exceptions on the constructors).
When writing a using statement:
using(SomeClass thing = new SomeClass())
{
//...
if (condition)
return;
//...
}
this will result in the following code:
SomeClass thing;
try
{
thing = new SomeClass();
//...
if (condition)
return;
//...
}
finally
{
if(thing != null)
{
thing.Dispose();
}
}
So all object declared using ( /* HERE */ ) will get disposed automatically. Objects declared inside the {} won't.
But you can of course nest (or stack) using statements:
using (var thing = new SomeClass())
using (var another = new Another())
using (var somethingElse = new Whatever())
{
//...
}
which in turn of course is just the syntactic sugar for writing
using (var thing = new SomeClass())
{
using (var another = new Another())
{
using (var somethingElse = new Whatever())
{
//...
}
}
}
because when a statement is followed by just one block of code (in this case another using-block) you can skip the curly braces...
When using two or more objects of the same type you can chain the declaratio within the using-statement:
using (MemoryStream stream = new MemoryStream(), stream2 = new MemoryStream())
{
//...
}
(Thanks to #Gratzy for pointing that out)
For me, the question does not match with the details, and the details have been addressed here a bunch but not the title question...
Does using dispose all the the objects declared in it?
NO, it does not. It only calls Dispose() for the object(s) in its declaration. It does not call Dispose() for objects declared in it.
I usually see this kind of thing in code
using(var sqlConn = new SqlConnection("connStr"))
using(var sqlCmd = new SqlCmd("CmdText", sqlConn))
{
sqlConn.Open();
var reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
//stuff is done
}
}
This will dispose and close both sqlConn and sqlCmd when the scope is complete for those but the reader that was declared in the using scope does not have Dispose() automatically called for it .
I'm writing a method that resets a logging system. I need to get an instance of a CsvFileLogWriter (a custom class) and pass it to the reset method. CsvFileLogWriter is disposable so I get a CA2000 warning tell me:
Warning 2 CA2000 : Microsoft.Reliability : In method 'Logger.InitializeCsvLogger
(string)', call System.IDisposable.Dispose on object 'tempWriter'
before all references to it are out of scope.
I've followed the instructions relating to CA2000 and I end up with the following method. However, I still get the CA2000 warning.
public static void InitializeCsvLogger(string path)
{
ILogWriter tempWriter = null;
try
{
tempWriter = new CsvFileLogWriter(path);
ResetWriter(tempWriter);
tempWriter = null;
}
finally
{
if (tempWriter != null)
tempWriter.Dispose();
}
}
Can someone please spot my mistake?
EDIT
I do not wish to dispose of the writer that is reference by tempWriter - this is not a temporary object, just a temporary reference. I only dispose of it if there is a failure within the try block (so tempWriter never gets set to null and the if-statement in the finally block clears up the resources.) I do not want tempWriter disposing of unless this failure occurs - the object itself must remain in use after being set in a property by ResetWriter(tempWriter). This is as per the CA2000 rules - see http://msdn.microsoft.com/en-us/library/ms182289.aspx?queryresult=true
For clarification, here is what ResetWriter does - Writer is a static property. The method disposes the old writer and sets the new one.
private static void ResetWriter(ILogWriter newWriter)
{
if (Writer != null)
Writer.Dispose();
Writer = newWriter;
}
EDIT
I think as SLaks stated that it's a false positive. If I take the contents of ResetWriter and put them in place of the call to ResetWriter (essentially reversing an Extract Method refactoring) the CA2000 goes away.
Or in other words, the following does not give the CA2000 warning:
public static void InitializeCsvLogger(string path)
{
ILogWriter tempWriter = null;
try
{
tempWriter = new CsvFileLogWriter(path);
if (Writer != null)
Writer.Dispose();
Writer = tempWriter;
tempWriter = null;
}
finally
{
if (tempWriter != null)
tempWriter.Dispose();
}
}
When you assign null to tempWriter:
tempWriter = null;
tempWriter no longer refers to the object you created. Therefore, there's no way for you to Dispose the object.
You should really use a using block in this case instead:
using(var tempWriter = new CsvFileLogWriter(path))
{
ResetWriter(tempWriter);
}
By doing that, you no longer have to worry about calling Dispose (or setting the reference to null).
This warning is a false positive.
The Code Analysis engine doesn't realize that ResetWriter needs the writer to stay alive, so it wants you to dispose it in all circumstances.
You should suppress the warning.
By writing tempWriter = null you're preventing it from getting disposed, since the finally block only runs after that.
You should use the using statement instead.
This answer is correct, but contradicts your actual intentions.
I am doing a code review, and have found alot of code with the following format:
public MyResponse MyMethod(string arg)
{
using (Tracer myTracer = new Tracer(Constants.TraceLog))
{
MyResponse abc = new MyResponse();
// Some code
return abc;
}
}
When I run a code analysis I get a CA2000 warning Microsoft.Reliability
Should the code be rewritten as:
public MyResponse MyMethod(string arg)
{
MyResponse abc = new MyResponse();
using (Tracer myTracer = new Tracer(Constants.TraceLog))
{
// Some code
}
return abc;
}
Or does it not matter?
Edit
The line on which it is reporting the warning is:
MyResponse abc = new MyResponse();
MyResponse is a standard Dataset.
The full error message is:
Warning 150 CA2000 : Microsoft.Reliability : In method 'xxxxx(Guid, Guid)', object 'MyResponse ' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'MyResponse ' before all references to it are out of scope.
No, it doesn't matter.
The finally block that's implicitly generated by the using statement to handle disposal will execute no matter where you put the return.
Are you sure that the CA2000 relates to myTracer and not abc? I would guess that the warning is occurring because MyResponse implements IDisposable and you're not disposing abc before returning. (Either way, your suggested rewrite should make no difference to the warning.)
Your rewrite will not fix that CA2000 warning, because the problem is not the Tracer object, but the MyResponse object.
The documentation states:
The following are some situations where the using statement is not enough to protect IDisposable objects and can cause CA2000 to occur.
Returning a disposable object requires that the object is constructed in a try/finally block outside a using block.
To fix the warning without messing with the stack trace of your exceptions (<- click, it's a link), use this code:
public MyResponse MyMethod(string arg)
{
MyResponse tmpResponse = null;
MyResponse response = null;
try
{
tmpResponse = new MyResponse();
using (Tracer myTracer = new Tracer(Constants.TraceLog))
{
// Some code
}
response = tmpResponse;
tmpResponse = null;
}
finally
{
if(tmpResponse != null)
tmpResponse .Dispose();
}
return response;
}
Why? Please see the example in the linked documentation.
The warning is probably about MyResponse, which is IDisposable.
Why does the warning appear?
If a MyResponse object is constructed, but code later in the method causes an exception to be thrown, then all references to this object will be lost (we only had one, and didn't manage to return it). This means that Dispose cannot be called on the object anymore, and we will be relying on the class finalizer to clean up any resources.
Does it matter?
Generally speaking, it will only matter if:
The IDisposable encapsulates a resource that might be needed "soon" by other parts of the program or by another process
An exception is thrown before the method returns, to trigger the "problem"
That resource is not released by the finalizer soon enough, or for some reason the finalizer never runs but your application doesn't go down
So no, it shouldn't really matter.
How to fix it?
public MyResponse MyMethod(string arg)
{
MyResponse abc = null;
try {
abc = new MyResponse();
using (Tracer myTracer = new Tracer(Constants.TraceLog))
{
// Some code
return abc;
}
}
catch {
if (abc != null) {
abc.Dispose();
}
throw;
}
}
This ensures that if control exits the method by means of an exception, abc is either null or has been properly disposed.
Update
It turns out when using this way of handling things, an exception explicitly thrown from inside MyMethod will be rethrown and have the line number of the first stack frame mutated to point to the throw; statement.
Practically this means that if you have multiple throw statements inside MyResponse, and they throw the same type of exception with the same message, you will not be able to tell which throw was responsible exactly when you catch the exception.
This is IMHO a purely academic problem, but I mention it for completeness.
It doesn't really matter. But, contrary to #Aliostad, I think version 2, with the return outside of the using block is better style.
My rationale goes like this:
The using block denotes something that is "opened" and "closed". This is a kind of cheep transaction. Closing the using block says we have done our work and it is safe now to continue with other stuff, like returning.
This warning is probably related to the principle of "single exit point". It is discussed here: http://c2.com/cgi/wiki?SingleFunctionExitPoint