When to dispose and why?

2019-01-25 09:49发布

I asked a question about this method:

// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
    XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
    TextWriter textWriter = new StreamWriter(filename);

    xmlSerializer.Serialize(textWriter, toSerialize);
    textWriter.Close();
}

in the response I got this as an added remark:

Make sure you always dispose disposable resources such as streams and text readers and writers. This doesn't seem to be the case in your SerializeObject method.

So, I can tell that this is going to seem super lame for someone who has been coding C# for a year or two, but why do I have to dispose it?

Is see that testWriter has a dispose method, but shouldn't garbage collection take care of that? I came from Delphi to C#. In Delphi I had to clean up everything, so this is not a case of me wanting to be lazy. I just was told that if you force freeing up the memory that your objects take then it can cause bad stuff. I was told to "Just let the garbage collector do it".

  1. So, why do I need to call dispose? (My guess is that it is because textWriter hits the disk.)
  2. Is there a list of objects I need to be careful with? (Or an easy way to know when I need to call dispose?)

标签: c# dispose
12条回答
对你真心纯属浪费
2楼-- · 2019-01-25 09:49

The rule of thumb here is pretty simple: always call Dispose() on objects that implement IDisposable (not all objects do). You won't always know the reason why an object had to implement Dispose, but you should assume that it is there for a reason.

The easiest way to make sure you do this is through using:

using (TextWriter tw = new StreamWriter(fileName))
{
   // your code here
}

This will call Dispose() automatically at the end of the using block (it's fundamentally the same as using a try/catch/finally with the Dispose() in the finally block).

For more information on how Dispose works with garbage collection, see here.

查看更多
一夜七次
3楼-- · 2019-01-25 09:49

If you know you're not going to use a certain resource you can simply dispose of it yourself; you will certainly be faster than the garbage collector and will allow others to use the file or whatever you have opened faster. The easiest way would be to use your TextWriter or any other resource in a using:

using (TextWriter textWriter = new StreamWriter(filename))
{
    xmlSerializer.Serialize(textWriter, toSerialize);
}

This basically ensures the TextWriter is disposed at the end. You don't need it any more than that, anyway.

查看更多
不美不萌又怎样
4楼-- · 2019-01-25 09:50

Garbage collector releases all resources, but the time when it does this is undefined. Dispose method provides a way to release unmanaged resources immediately.

查看更多
爷的心禁止访问
5楼-- · 2019-01-25 09:50

Well actually you already are disposing it since the textWriter.Close Method does it.

public virtual void Close()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

So you could change your code to. This

public static void SerializeObject<T>(this T toSerialize, String filename)
{
    TextWriter textWriter;
    try
    {
         XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
         textWriter = new StreamWriter(filename);

          xmlSerializer.Serialize(textWriter, toSerialize);
    }
    finally
   {
       textWriter.Close();
   }

Which is pretty similar to what the using() does in the other answers.

The impact of not doing this is that if an error occurs with Serialize it would be a while before the Framework gave up its file lock (when it Processes the fReachable queue).

I know FxCop tells you when to implment IDisposable but I don't think there's any easy way to find out when you need to call Dispose other than looking at the Docs and seeing if an object implments IDisposable (or intellisense).

查看更多
Emotional °昔
6楼-- · 2019-01-25 09:52

A programmer thinking that one doesn't have to worry about disposing things because a finalizer will take care of them is like a driver thinking one doesn't have to worry about avoiding collisions because the car has an airbag. Yes, an airbag will make things more survivable, but...

查看更多
放荡不羁爱自由
7楼-- · 2019-01-25 09:53

If you are using native resources (for example file handles) then you should call Dispose() to close them soon, and not when the GC runs(which might be much later in higher gc generations). And you want to close the file since file access usually locks the file in some way.

查看更多
登录 后发表回答