Do you need to dispose of objects and set them to

2018-12-31 16:30发布

Do you need to dispose of objects and set them to null, or will the garbage collector clean them up when they go out of scope?

12条回答
冷夜・残月
2楼-- · 2018-12-31 16:59

I agree with the common answer here that yes you should dispose and no you generally shouldn't set the variable to null... but I wanted to point out that dispose is NOT primarily about memory management. Yes, it can help (and sometimes does) with memory management, but it's primary purpose is to give you deterministic releasing of scarce resources.

For example, if you open a hardware port (serial for example), a TCP/IP socket, a file (in exclusive access mode) or even a database connection you have now prevented any other code from using those items until they are released. Dispose generally releases these items (along with GDI and other "os" handles etc. which there are 1000's of available, but are still limited overall). If you don't call dipose on the owner object and explicitly release these resources, then try to open the same resource again in the future (or another program does) that open attempt will fail because your undisposed, uncollected object still has the item open. Of course, when the GC collects the item (if the Dispose pattern has been implemented correctly) the resource will get released... but you don't know when that will be, so you don't know when it's safe to re-open that resource. This is the primary issue Dispose works around. Of course, releasing these handles often releases memory too, and never releasing them may never release that memory... hence all the talk about memory leaks, or delays in memory clean up.

I have seen real world examples of this causing problems. For instance, I have seen ASP.Net web applications that eventually fail to connect to the database (albeit for short periods of time, or until the web server process is restarted) because the sql server 'connection pool is full'... i.e, so many connections have been created and not explicitly released in so short a period of time that no new connections can be created and many of the connections in the pool, although not active, are still referenced by undiposed and uncollected objects and so can't be reused. Correctly disposing the database connections where necessary ensures this problem doesn't happen (at least not unless you have very high concurrent access).

查看更多
无色无味的生活
3楼-- · 2018-12-31 17:01

If the object implements IDisposable, then yes, you should dispose it. The object could be hanging on to native resources (file handles, OS objects) that might not be freed immediately otherwise. This can lead to resource starvation, file-locking issues, and other subtle bugs that could otherwise be avoided.

See also Implementing a Dispose Method on MSDN.

查看更多
大哥的爱人
4楼-- · 2018-12-31 17:02

There's a good discussion on the subject (along with the history behind the Dispose pattern) in this episode of .NET Rocks!

http://www.dotnetrocks.com/default.aspx?showNum=10

查看更多
爱死公子算了
5楼-- · 2018-12-31 17:03

You never need to set objects to null in C#. The compiler and runtime will take care of figuring out when they are no longer in scope.

Yes, you should dispose of objects that implement IDisposable.

查看更多
查无此人
6楼-- · 2018-12-31 17:04

Normally, there's no need to set fields to null. I'd always recommend disposing unmanaged resources however.

From experience I'd also advise you to do the following:

  • Unsubscribe from events if you no longer need them.
  • Set any field holding a delegate or an expression to null if it's no longer needed.

I've come across some very hard to find issues that were the direct result of not following the advice above.

A good place to do this is in Dispose(), but sooner is usually better.

In general, if a reference exists to an object the garbage collector (GC) may take a couple of generations longer to figure out that an object is no longer in use. All the while the object remains in memory.

That may not be a problem until you find that your app is using a lot more memory than you'd expect. When that happens, hook up a memory profiler to see what objects are not being cleaned up. Setting fields referencing other objects to null and clearing collections on disposal can really help the GC figure out what objects it can remove from memory. The GC will reclaim the used memory faster making your app a lot less memory hungry and faster.

查看更多
呛了眼睛熬了心
7楼-- · 2018-12-31 17:05

Objects will be cleaned up when they are no longer being used and when the garbage collector sees fit. Sometimes, you may need to set an object to null in order to make it go out of scope (such as a static field whose value you no longer need), but overall there is usually no need to set to null.

Regarding disposing objects, I agree with @Andre. If the object is IDisposable it is a good idea to dispose it when you no longer need it, especially if the object uses unmanaged resources. Not disposing unmanaged resources will lead to memory leaks.

You can use the using statement to automatically dispose an object once your program leaves the scope of the using statement.

using (MyIDisposableObject obj = new MyIDisposableObject())
{
    // use the object here
} // the object is disposed here

Which is functionally equivalent to:

MyIDisposableObject obj;
try
{
    obj = new MyIDisposableObject();
}
finally
{
    if (obj != null)
    {
        ((IDisposable)obj).Dispose();
    }
}
查看更多
登录 后发表回答