Is it possible to write C# so that objects are garbage collected when they fall out of scope?
For example, in the below code an 'image'object will be created and then garbage collected at some unknown point in the future
void MyFunction() {
Bitmap image = RetrieveImage();
开发者_开发百科DoSomething(image);
}
What about
void MyFunction() {
DoSomething(RetrieveImage());
}
In this case is the object garbage collected once it moves out of scope i.e. After the end of MyFunction. If not is there somewhere to enforce this?
No. In fact, you don't really want it to be garbage collected - prompting the garbage collector very frequently will reduce performance.
What you do want is to dispose of the unmanaged resources in a timely manner - and that's where IDisposable
comes in, along with the using
statement:
void MyFunction()
{
using (Bitmap image = RetrieveImage())
{
DoSomething(image);
}
}
That will call image.Dispose()
as it leaves the using
statement, whether or not DoSomething
threw an exception.
You do have to use the extra variable though - unless you change DoSomething
to take a Func<Bitmap>
instead, so instead of:
void DoSomething(Bitmap image)
{
// Code here
}
...
DoSomething(RetrieveImage());
you'd have:
void DoSomething(Func<Bitmap> imageProvider)
{
using (Bitmap image = imageProvider())
{
// Code here
}
}
...
DoSomething(() => RetrieveImage());
Note that that doesn't give the opportunity to pass in a bitmap without it being disposed - which could be a problem if you want to use it again later. Still, it's a nice technique to at least know about.
EDIT: As mbeckish has pointed out in his comments, there isn't very much benefit here over just disposing of the bitmap within RetrieveImage
. Here's a variant on the pattern though:
public void ApplyToEachLineInFile(string file, Action<string> action)
{
using (TextReader reader = File.OpenText(file))
{
string line;
while ((line = reader.ReadLine()) != null)
{
action(line);
}
}
}
Here the "acquire and dispose" logic is encapsulated, without the caller worrying about it - but the caller can still be very flexible in terms of the complexity of logic they pass in.
Garbage collection does not happen when an object falls out of scope. Rather it is an automatic memory management function from the framework.
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
You can force .Net to collect the garbage, but unless you are experiencing serious memory issues, I would not recommend you go down that path.
NOTE: You don't want to do this. The .NET garbage collector is "smarter" than you (or me, or Jon Skeet or anyone else).
try
{
Bitmap image = RetrieveImage();
DoSomething(image);
}
finally
{
GC.Collect();
}
(this is assuming that none of the objects that fall out of scope implement IDisposable)
You can enforce Garbage Collection with:
System.GC.Collect()
after Disposing it properly (see Jons Answer for the using() {} - Syntax).
<edit>
Don't forget (as I just did)
System.GC.WaitForPendingFinalizers();
afterwards.
</edit>
Although it is not recommended - as Jon said.
精彩评论