Should I always use Dispose?

Asked

Viewed 12,489 times

29

A question I have always had. I see that there are many objects with Ispose method, I read about that serves to free resources. But this doesn’t happen automatically?

If I am creating a class that inside it I use a form and some controls during the execution of the class. As, for example:

public class A
{
   private Form Frm {get; set;}
   private Label Lbl {get;set;}

   public A()
   {
      Frm = new Form();
      Lbl = new Label();
      Frm.Controls.Add(Lbl);
   }

   public void Show()
   {
      Frm.ShowDialog();
   }
}

This class is just for example of the situation. I should worry about using the interface Idisposable? When I should use Dispose, when the object is destroyed it does not automatically release to me all resources?

  • 1

    You should use Dispose when the object says in your documentation that it is not treated by Garbage Collector (and therefore should be disposed). An example is the class System.Drawing.Bitmap.

  • 1

    I understand, but the answer seems a little vague to me. In this example I gave that I have a Form and a Label, wouldn’t I need a Dysplasia method? If it was a database handling class, it should use a Dispose that calls the connection Dispose?

  • The features of an object are automatically released by the GC after the object is no longer needed. But the resources automatically released are the so-called managed resources (or Managed Resources). Already the unmanaged resources (or Unmanaged Resources), as access to the disk, to the network, Handles, connections to the database... are not automatically released and require extra care, which can go through the implementation of the interface Idisposable. A hint is: if the object you consume is Disposable, try to secure the call to your method Dispose.

2 answers

32


There seems to be some confusion of concepts.

Resource release is different from memory release. The Garbage Collector releases memory when it can and finds it necessary. It does not release resources.

What is to release resources?

When you have access to something "something" that has a link with the application at any given time this link needs to be finalized somehow. A typical example is the file on a disk. To access it, you open it by creating a link with the application. At some point this file needs to be closed by undoing this link. This needs to be done as soon as possible. You cannot wait for the Garbage Collector take action. You have no control when it will release the memory, GC tracings are not deterministic.

There are languages, usually without GC or with Counting, that the release of memory and release of the resource can be done in a synchronized way.

All classes that need this release must implement the interface IDisposable, ie, need to create an implementation of the method Dispose() which will end the linking of the resource with the application. It is therefore common for the implementation to call the method Close().

Someone might think, call the Close() logo. Ok, you can do this. But you need a way to do this in a standardized way. You need to create a design pattern.

When the program creates an instance of a class that implements the Dispose(), he must ensure that the method Dispose() is called one way or another.

The most common is to use the statement using. This way you create a scope, so when the instance goes out of scope, the method will be called "automatically" without you worrying. But you have to worry about creating the instance the right way, you have to create as using. Some static analysis tools programs can help you by letting you know that you forgot to create the instance with the using. Don’t be without the Resharper.

Because the Form you don’t need this?

Of course you can call the Close() on its own. What matters is Close() be called. In this case the Close() will call the Dispose() if necessary.

An implicit closure of a form may call the Close() for you. But it depends on how it was created.

The ShowDialog() does not call the Close() on its own. Then you should call. The ShowDialog() closes the Form in a different way (in a modal way), not providing the necessary untying. When it finishes running it is as if it has just been hidden away. Then you could call:

public void Show() {
    using (var frm = new Form()) {
        frm.ShowDialog();
    }
}

If this is not possible, you will have to ensure, otherwise frm is released when no longer required.

On the other hand if you call form1.Show() or Application.Run(new Form1()), the Close(), and therefore the Dispose() will be called by you. When you no longer want to show the form you should call the Hide(), otherwise the Form will be destroyed. View documentation.

Note that this destruction is related to the resource and not necessarily to the memory allocated to it. The memory will only be displaced by the GC.

Creating a class IDisposable

On the other hand if your concern is to implement a IDisposable in your new class, it depends on whether you’re using a resource in it. Usually an external resource to the application, something that needs to be unlinked. Usually this is done at a lower abstraction level, where you will effectively manipulate the external resource more concretely.

The fact that you are using resources within your class does not require the implementation of IDisposable. If you can guarantee the release of all resources within your own class, then it does not need to have the Dispose() hers.

But if this can’t be guaranteed, then you need a Dispose() implemented in it and probably within it all Dispose() of the instances that need to be released should be called.

And if I forget to call Dispose()?

Any attempt to access the resource can conflict (be denied, for example). But this will only occur until the first garbage collection. If there is no further reference to the instance, the GC will call the Finalize() and this will call the Dispose(), if necessary. Then the release of resources will occur at some point, even if it is at the close of the application.

This is valid if there is no catastrophic breakup. Of course, if . NET cannot complete correctly, none of this will happen. But then the operating system will probably resolve the situation by destroying all remaining links to an application that no longer exists, as well as the memory allocated to it. If the termination occurs by boot of the machine nor need to worry about anything, everything will be released for obvious reasons.

  • Taking advantage of the topic, its good explanation. In case my class needs Dispose, I must call you at the destroyer?

  • It’s one of the possibilities. But you have to be careful. I myself do not know all the situations that a destructor should be used and when it should be avoided or preferred the use of Finalize(). It seems to me that this is a typical case for its use, at least the documentation shows so. http://msdn.microsoft.com/en-us/library/vstudio/b1yfkh5e(v=vs.110).aspx. See more in OS: http://stackoverflow.com/questions/158174/why-would-you-ever-implement-finalize and http://stackoverflow.com/questions/628752/why-call-disposefalse-inthe-destructor And...

  • http://stackoverflow.com/questions/339063/what-is-the-difference-between-using-idisposable-vs-a-destructor-in-c e http://stackoverflow.com/questions/456213/destructor-vs-idisposable e http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface. It’s not what you need to call, but if you don’t call, you may have resource leak. This is the last opportunity that the application has to make the release of a resource that probably should have been released already. After this, only the OS can make the release at the end of the application. Then we can say that it is mandatory.

  • 1

    That is wrong: "If there is no further reference to the instance, GC will call Finalize() and it will call Dispose(), if necessary." In fact, the standard implementation of finalize (the implementation provided by Objetc) does nothing and is even called by the GC if it has not been implemented in a daughter class. Strictly speaking, to ensure that unmanaged resources are released in case the consumer forgets to call the Disposis, it is necessary to explicitly implement the finalize (in the case of C#, the destructor) for him to invoke the Disposis.

  • 1

    From what I’ve seen, most implementations of Disposis in C# are incomplete because they are based on misconceptions like this. This only does not cause major problems because in practice we usually use classes . Net to access unmanaged resources, and these in turn make a complete implementation of the standard Disposable, so that when capped by GC end up making the necessary releases even if the programmer forgot to call the Disposis or has made a bad implementation of its own Disposis.

8

You must use the Dispose to free resources before the Garbage Collector passes to clear the reference to your object.

This should be done, because there are scenarios where Garbage Collector can take a long time to clear its object (or in very particular cases, it may not even go through to clean it, leaving it alive until the end of the application). In the meantime, resources (such as images, database connections, etc.) remain allocated.

However, if you know that you will no longer use the object, you should call the method Dispose to manually release the resources. This becomes especially important in scenarios such as large web applications that use database connections (DBMS can limit the amount of simultaneous connections, so the sooner you release a connection, the faster another connection can be made next).

Take a look at these other questions here, along with the answers, which can provide you with more information and examples:

Concepts of Mesomorphic Allocation and Liberation in C#

What it means '~' in front of the constructor of a C class#

Browser other questions tagged

You are not signed in. Login or sign up in order to post.