Let's have an example:
using (var someObject = new SomeObject())
{
var someOtherObject = new SomeOtherObject();
someOtherObject.someMethod();
}
SomeOtherObject also implements IDisposable.
Will be SomeOtherObject also disposed when SomeObject get disposed ? What will happen to the SomeOtherObject ?
(disposing of SomeOtherObject is not implemented in the Dispose method of SomeObject)
No. Only fields in the using clause will be disposed. In your case only someObject.
Basically that code gets translated into
var someObject = null;
try
{
someObject = new SomeObject()
var someOtherObject = new SomeOtherObject();
someOtherObject.someMethod();
}
finally
{
if (someObject != null )
someObject.Dispose()
}
No, SomeOtherObject will not be Disposed.
Your code is restructured by the compiler as follows:
var someObject = new SomeObject();
try
{
var someOtherObject = new SomeOtherObject();
someOtherObject.someMethod();
}
finally
{
if (someObject != null)
someObject.Dispose();
}
No someOtherObject will not disposed.
Your code would traslates in something like this:
var someObject = new SomeObject();
try
{
var someOtherObject = new SomeOtherObject();
someOtherObject.someMethod();
}
finally
{
((IDisposable)someObject).Dispose();
}
So, there are no additional calls to any newly created object would performed.
quote from MSDN directly:
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 (when you use it as shown earlier) 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.
Thus only the object declared and instantiated in the using statement will be disposed. For this kind of problem I would suggest you to do some test before post the question.
someOtherObject will be collected normally by the Garbage Collector. If you did not provide an appropriate finalizer (destructor) that calls Dispose(), this will never get called. Only someObject.Dispose() will be called when execution flow leaves the using block.
You should write it like this:
using (var someObject = new SomeObject()) {
using (var someOtherObject = new SomeOtherObject()) {
someOtherObject.someMethod();
}
}
This can get out of hand if your method is creating a lot of disposable objects, common in painting code. Refactor into a helper method or switch to an explicit finally block.
The Dispose method of object that is referenced by someObject will be called when control leaves the using block. You can SuppressFinalize in Dispose method in which case system will not call that object's finalizer (otherwise it will).
The object that referenced by someOtherObject will, however, be collected by GC at appropriate time, because as the control leave the block, it won't be referenced by any object and will be marked for collection.
Not sure if this is where you are coming from; the someOtherObject is not going to be accessible outside the using block; because of the scoping rules.
using (Stream stream = File.OpenRead(#"c:\test.txt"))
{
var v1 = "Hello"; //object declared here, wont be accessible outside the block
stream.Write(ASCIIEncoding.ASCII.GetBytes("This is a test"), 0, 1024);
} //end of scope of stream object; as well as end of scope of v1 object.
v1 = "World!"; //Error, the object is out of scope!
Compiler error: "The name v1 does not exist in the current context."
Even following would throw an error.
{
int x=10;
}
x = 20; //Compiler error: "The name x does not exist in the current context."
See this and this for more help.
Related
I have a question about the following code:
DisposableObject holdon = null;
using (DisposableObject o = new DisposableObject())
{
Console.WriteLine("Inside using block");
holdon = o;
}
holdon.Method();
When I ran this code, I expected to get an exception on the line holdon.Method(), but to my surprise, It happily called Method() without any problem. I was able to confirm that DisposableObject.Dispose() is being called on o upon hitting the end of the using block. This raises a question that I didn't have a lot of luck finding the answer to on MSDN. After the using block, holdon is definitely still pointing to a valid object in memory despite the fact that Dispose() was called. So does holdon still point to the same object previously pointed to by o, or does it point to a copy of o?
Disposing object is not related to removing object from memory. It only means calling Dispose() method on that object. All further actions depend on IDisposable implementation of the object you have disposed. In some cases object is set to 'disposed' state and all further actions raise an exception (ObjectDisposedException). But you are free to do anything (or not do) when you implement IDisposable.
E.g. this is a totally valid IDisposable implementation (fiddle):
public class CrazyDisposable : IDisposable
{
public int Counter { get; private set; }
public void Dispose() => Counter++;
}
Further reading: using statement (C# Reference).
And particularly part which explains why it's better to limit the scope of the disposable object to the using block:
You can instantiate the resource object and then pass the variable to
the using statement, but this is not a best practice. In this case,
the object remains in scope after control leaves the using block even
though it will probably no longer have access to its unmanaged
resources. In other words, it will no longer be fully initialized. If
you try to use the object outside the using block, you risk causing an
exception to be thrown. For this reason, it is generally better to
instantiate the object in the using statement and limit its scope to
the using block.
as you can see - it's allowed, but you risk when you access the disposed object.
the using statement is just shorthand for
DisposableObject holdon = null;
{ //This "{" is here to limit the scope of "o"
DisposableObject o = new DisposableObject()
try
{
Console.WriteLine("Inside using block");
holdon = o;
}
finally
{
if(o != null)
o.Dispose();
}
}
holdon.Method();
So if calling
o.Dispose();
o.Method();
in normal code does not cause a exception then calling holdon.Method() after o.Dispose() will not cause a exception either.
I noticed the following object disposal code pattern in a C# project and I was wondering if it's acceptable (although it works).
public object GetData()
{
object obj;
try
{
obj = new Object();
// code to populate SortedList
return obj;
}
catch
{
return null;
}
finally
{
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
}
For this example, I'm using a general 'object' instead of the actual IDisposable class in the project.
I know that the 'finally' block will be executed every time, even when the value is returned, but would it affect the return value (or would it be a new object instance) in any way since the object is being set to null (for what seems like object disposal and GC purposes).
Update 1:
I tried the following snippet and the return object is non-null, although the local object is set to null, so it works, which is a bit strange considering some of the comments below:
public StringBuilder TestDate()
{
StringBuilder sb;
try
{
sb = new StringBuilder();
sb.Append(DateTime.UtcNow.ToString());
return sb;
}
catch
{
return null;
}
finally
{
sb = null;
}
}
Btw, I'm using C# 4.0.
P.S. I'm just reviewing this project code. I'm not the original author.
Update 2:
Found the answer to this mystery [1]. The finally statement is executed, but the return value isn't affected (if set/reset in the finally block).
[1] What really happens in a try { return x; } finally { x = null; } statement?
This code will compile fine (assuming that you are not actually using an Object but something that implements IDisposable), but it probably won't do what you want it to do. In C#, you don't get a new object without a new; this code will return a reference to an object that has already been disposed, and depending on the object and what Dispose() actually does, trying to use a disposed object may or may not crash your program.
I assume the idea is to create an object, do some stuff with it, then return the object if successful or null (and dispose the object) on failure. If so, what you should do is:
try {
obj = new MyClass();
// ... do some stuff with obj
return obj;
}
catch {
if(obj != null) obj.Dispose();
return null;
}
Simply using the using statement achieves the same result as that, and is the standard practice
public int A()
{
using(IDisposable obj = new MyClass())
{
//...
return something;
}
}
I would, however, advise against returning your IDisposable object.
When you dispose of an object, it is supposed to be considered "unusable". And so, why return it?
If the object's lifetime needs to be longer than the method A's lifetime, consider having the calling method B instantiate the object, and pass it as a parameter to method A.
In this case, method Bwould be the one using the using statement, inside which it would call A.
If you are returning an IDisposable object, then it is the responsibility of your caller to dispose of it:
public IDisposable MakeDisposableObject()
{
return new SqlConnection(""); // or whatever
}
caller:
using (var obj = MakeDisposableObject())
{
}
It makes less than no sense for your method to dispose of an object and then return it. The disposed object will be of no value to the caller. In general, referencing a disposable object which has been disposed should produce an ObjectDisposedException.
A few observations.
That code wouldn't compile because object doesn't have a .Dispose() method.
Why wouldn't you use IDisposable?
Why would you dispose of an object that is being returned, since returning you would return an object for the purpose of some other code to use it. The concept of "disposing" of something is to give it a chance to clean up after itself and its used, un-managed resources. If you are returning an object that is supposed to be used elsewhere, but has unmanaged resources that you want to clean up before the object gets used anywhere else, then you shuld really have 2 separate objects. One to load some data that would be disposable, and another object that would contain the usable loaded content that you want to pass around. An example of this would be something like stream readers in the .NET framework. You would normally new a stream reader, read it into a byte[] or some other data object, .Dispose() the stream reader, then return the byte[]. The "loader" that has some resources to dispose of in a timely fashion is separate from the object containing the "loaded" data that can be used without needing to be disposed.
If you call a constructor from a within a using statement the object is automatically disposed is wrapped it with a try/catch block. That is an object initializer block in the constructor.
But what becomes with member types that are initialized in the same statement? e.g:
class TypeThatThrowsAnException
{
public TypeThatThrowsAnException()
{
throw new Exception();
}
}
using (SomeDisposable ds = new SomeDisposable() {
MemberThatThrowsAnException m = new TypeThatThrowsAnException()
})
{
// inside using statement
ds.doSomething();
}
What happens with MemberThatThrowsAnException when it throws an exception when SomeDisposable is initialized, i.e., the code block is executed?
And does it make any difference if we call those members constructors outside the scope of the using block?
class TypeThatThrowsAnException
{
public TypeThatThrowsAnException()
{
throw new Exception();
}
}
class SomeClass
{
public static TypeThatThrowsAnException StaticMember
{
get
{
return new TypeThatThrowsAnException();
}
}
}
using (SomeDisposable ds = new SomeDisposable() {
MemberThatThrowsAnException = SomeClass.StaticMember
})
{
// inside using statement
ds.doSomething();
}
In some scenarios this can be pretty nice and readable, but I would like to know if thare are any caveats or pitfalls in this way. Or that it is a no-go all the way. Besides that you need to keep the readability in mind.
Object initializers are in some sense a red herring here... but they're one example of where a problem is avoidable.
The object isn't "guarded" by the using statement until the resource acquisition expression has completed normally. In other words, your code is like this:
SomeDisposable tmp = new SomeDisposable();
tmp.MemberThatThrowsAnException = new TypeThatThrowsAnException();
using (SomeDisposable ds = tmp)
{
// Stuff
}
That's more obviously problematic :)
Of course the solution is to assign the property inside the using statement:
using (SomeDisposable ds = new SomeDisposable())
{
MemberThatThrowsAnException = new TypeThatThrowsAnException();
// Stuff
}
Now we're only relying on the constructor of SomeDisposable to clean up after itself if it ends up throwing an exception - and that's a more reasonable requirement.
Find this post on Ayende's blog on the subject. It's about object initializers in using statements but it seems somehow related to your question.
From what I can see, your SomeDisposable class has a property of type TypeThatThrowsAnException, that you're initializing as you instantiate the SomeDisposable - yes ?
using () i.e. the Dispose pattern is a short-hand that actually emits this: -
SomeDisposable ds = null;
try
{
ds = new SomeDisposable();
}
finally
{
if (ds != null)
ds.Dispose();
}
So if the constructor for your type throws an exception, control will immediately pass to the finally block.
I am returning the variable I am creating in a using statement inside the using statement (sounds funny):
public DataTable foo ()
{
using (DataTable properties = new DataTable())
{
// do something
return properties;
}
}
Will this Dispose the properties variable??
After doing this am still getting this Warning:
Warning 34 CA2000 : Microsoft.Reliability : In method 'test.test', call System.IDisposable.Dispose on object 'properties' before all references to it are out of scope.
Any Ideas?
Thanks
If you want to return it, you can't wrap it in a using statement, because once you leave the braces, it goes out of scope and gets disposed.
You will have to instantiate it like this:
public DataTable Foo()
{
DataTable properties = new DataTable();
return properties;
}
and call Dispose() on it later.
Yes, it will dispose it - and then return it. This is almost always a bad thing to do.
In fact for DataTable, Dispose almost never does anything (the exception being if it's remoted somewhere, IIRC) but it's still a generally bad idea. Normally you should regard disposed objects as being unusable.
Supposedly, this is the pattern for a factory method that creates a disposable object. But, I've still seen Code Analysis complain about this, too:
Wrapper tempWrapper = null;
Wrapper wrapper = null;
try
{
tempWrapper = new Wrapper(callback);
Initialize(tempWrapper);
wrapper = tempWrapper;
tempWrapper = null;
}
finally
{
if (tempWrapper != null)
tempWrapper.Dispose();
}
return wrapper;
This should guarantee that if the initialization fails, the object is properly disposed, but if everything succeeds, an undisposed instance is returned from the method.
MSDN Article: CA2000: Dispose objects before losing scope.
Yes. Why are you using the using keyword on something you don't want disposed at the end of the code block?
The purpose of the using keyword is to dispose of the object.
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
The point of a using block is to create an artificial scope for a value/object. When the using block completes, the object is cleaned up because it is no longer needed. If you really want to return the object you are creating, than it is not a case where you want to use using.
This will work just fine.
public DataTable foo ()
{
DataTable properties = new DataTable();
// do something
return properties;
}
Your code using the using keyword expands to:
{
DataTable properties = new DataTable();
try
{
//do something
return properties;
}
finally
{
if(properties != null)
{
((IDisposable)properties).Dispose();
}
}
}
Your variable is being disposed by nature of how using works. If you want to be able to return properties, don't wrap it in a using block.
The other responses are correct: as soon as you exit the using block, your object is disposed. The using block is great for making sure that an object gets disposed in a timely manner, so if you don't want to rely on the consumers of your function to remember to dispose the object later, you can try something like this:
public void UsingDataContext (Action<DataContext> action)
{
using (DataContext ctx = new DataContext())
{
action(ctx)
}
}
This way you can say something like:
var user = GetNewUserInfo();
UsingDataContext(c => c.UserSet.Add(user));
I was reading another answer. And it made me wonder, when do does one need to explicitly call Dispose if I am using using statements?
EDIT:
Just to vindicate myself from being a total know-nothing, the reason I asked was because someone on another thread said something implying there was a good reason to have to call Dispose manually... So I figured, why not ask about it?
You don't. The using statement does it for you.
According to MSDN, this code example:
using (Font font1 = new Font("Arial", 10.0f))
{
byte charset = font1.GdiCharSet;
}
is expanded, when compiled, to the following code (note the extra curly braces to create the limited scope for the object):
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
Note: As #timvw mentioned, if you chain methods or use object initializers in the using statement itself and an exception is thrown, the object won't be disposed. Which makes sense if you look at what it will be expanded to. For example:
using(var cat = new Cat().AsDog())
{
// Pretend a cat is a dog
}
expands to
{
var cat = new Cat().AsDog(); // Throws
try
{
// Never reached
}
finally
{
if (cat != null)
((IDisposable)cat).Dispose();
}
}
AsDog will obviously throw an exception, since a cat can never be as awesome as a dog. The cat will then never be disposed of. Of course, some people may argue that cats should never be disposed of, but that's another discussion...
Anyways, just make sure that what you do using( here ) is safe and you are good to go. (Obviously, if the constructor fails, the object won't be created to begin with, so no need to dispose).
Normally you don't. This is the point of the using statement. There is however a situation where you have to be careful:
If you reassign the variable to another value the using statement will only call the Dispose method on the original value.
using (someValue = new DisposableObject())
{
someValue = someOtherValue;
}
The compiler will even give you a Warning about this:
Possibly incorrect assignment to local 'someValue' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
Be careful when using c# 3.0 object initializers though. An example can be found here: http://ayende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx
Never. It will call Dispose once the statements inside using blocks finish execution.
The whole point of the using statement is that if your object implements IDisposable, the dipose will be called at the end of the code block. That's what it's there for, to do it automaticaly for you.
As far as i know
using (var myDisposable = new MyDisposable())
{
...
}
is basically translated by the compiler to
var myDisposable = new MyDisposable()
try
{
...
}
finally
{
myDisposable.Dispose();
}