What is the difference between Idisposable implementations?

Asked

Viewed 1,716 times

8

I confess that I still don’t understand everything about how to manipulate the destruction of an object in the C# and now, as I’m testing Visual Studio 2015 Preview, when implementing a database connection class I went to include the inheritance of IDisposable and I used the option Implement interface with Dispose Pattern.

Then the following code was included in my class:

#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls

protected virtual void Dispose(bool disposing)
{
    if (!disposedValue)
    {
        if (disposing)
        {
            // TODO: dispose managed state (managed objects).
        }

        // TODO: free unmanaged resources (unmanaged objects) and override a 
        // finalizer below.
        // TODO: set large fields to null.

        disposedValue = true;
    }
}

// TODO: override a finalizer only if Dispose(bool disposing) above has code 
// to free unmanaged resources.
// ~DBConnection() {
//   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
//   Dispose(false);
// }

// This code added to correctly implement the disposable pattern.
public void Dispose()
{
    // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
    Dispose(true);
    // TODO: uncomment the following line if the finalizer is overridden above.
    // GC.SuppressFinalize(this);
}
#endregion

I couldn’t understand these comments with All on the method finalize ~DBConnection(), about the GC.SuppressFinalize(this); and on the method Dispose(bool disposing) and all its contents...

Checking further options saw the following implementation:

public void Dispose()
{
    ((IDisposable)connection).Dispose();
}

And of course, we have the following:

public void Dispose()
{
    throw new NotImplementedException();
}

That I would implement as is usually shown in examples on the web:

public void Dispose()
{
    if (connection != null && connection.State == ConnectionState.Open)
    {
        connection.Close();
        connection = null;
    }
    GC.SuppressFinalize(this);
}

Well, on the first example of implementation with all those comments, I understood that there is an explanation of the implementation options.

Can anyone help me understand the difference between these methods and the indications of the first method with the comments?

  • You just need to implement IDisposable if using resources not managed by CLR. https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110). aspx

  • but @bfavaretto, what would be the "unmanaged resources"? And what is the difference between the ways of implementing IDisposable? Finally, after I’ll create a question about managing connections in c#. Pool of connections, more than one command and reader ... let’s see.. Thank you!

  • 1

    James, everything you program on . net is compiled into an intermediate language interpreted by the . net virtual machine (the CLR). This type of code is managed by CLR (which handles garbage collection, among other bureaucracies). Code compiled for machine language (for example, written in C) can be integrated into your program, but is not managed by CLR and you need to manually take care of certain details. But I’ll stop here and let . net experts answer :)

2 answers

3


Several things. I will translate the first snippet of code to be clearer, and discuss each method:

protected virtual void Dispose(bool disposing)
{
    if (!disposedValue)
    {
        if (disposing)
        {
            // TODO: fazer dispose dos managed objects.
        }

        // TODO: liberar recursos unmanaged (unmanaged objects) e fazer override do finalizador.
        // TODO: campos grandes devem receber valor null.

        disposedValue = true;
    }
}

First I need to explain what objects are Managed and Unmanaged.

  • Objects Managed are those who are being controlled directly by Garbage Collector. That is, class objects in your system are usually Managed;
  • Objects Unmanaged are the reverse. A preview database, for example, written in a DLL other than the .NET. Normally objects like this have their own memory release procedure specified by the technology provider.

Within the if you must put any and all code additional that allows the immediate release of machine resources. Reset large variables in memory, for example.

Just below (on the resource part Unmanaged) you should put any and all code that involves use of resources that . NET does not have any control, such as a buffer from a printer or a disk driver. In a database context, close the connection, (which uses a socket other than. NET, but connected to a. NET code).

The idea of this destroyer:

~DBConnection() 
{
    // Não mude este código. Ele só está aqui a título de exemplo.
    Dispose(false);
}

Is to avoid any automatic memory releases by Garbage Collector. You indicate to Garbage Collector that your code will coordinate the destruction of the object.

Let’s go back to the example of buffers slow (disks and printers). Connection to the controllers takes time. If you release the object before, you lose the reference to communicate with the controller and ensure that everything was done right. This is critical when you need to perform, for example, some operation of flush. Releasing the object earlier may cause the communication to be interrupted and cause some inconsistency problem between the parties in the communication.

A socket database closure is a classic case of this. Closing the connection is recommended to be done after the if.

Finally:

public void Dispose()
{
    if (connection != null && connection.State == ConnectionState.Open)
    {
        connection.Close();
        connection = null;
    }
    GC.SuppressFinalize(this);
}

GC.SuppressFinalize(this); indicates that the destructor should not be called immediately. Closing the connection is a chain of procedures, and the code must ensure that the object exists as long as possible to avoid problems.

After a while, the Garbage Collector make routine checks and, when verifying that the object has no more references, eliminate the object. This is safer than asking for immediate release of the object.

-1

James, the first thing to understand is that the Garbage Collector (or Garbage collection) is automatic.

The Dispose Pattern would then be a design pattern that aims to manipulate the state of destruction of objects by CLR (Common Language Runtime).

In other words, you can indicate when an object may or may not be destroyed by implementing the class described in the question.

GC.SuppressFinalize(this); tells the CRL not to finalize the specified object (in the case, connection).

From period to period, GB does a refresh to check whether or not the "heap" objects are being used by the application and performs operations to clear them from memory.

The Dispose Pattern then develops conceptual and practical ways to manage these "disposables" objects by forcing them to "disappear" from memory or suppressing the automatic request to delete from memory.

  • Just about the GC.SuppressFinalize(this);, he suppresses the completion by Garbage Collector of the class that makes up the connection, and not the connection in itself.

  • I don’t understand the... connection is the object to be Disposable by GB. SuppressFinalize is informing GB that this object has been completely cleaned

  • No. I have something like public class DBConnection { private SqlConnection connection; ... } then GC.SuppressFinalize(this); says that DBConnection was cleaned, and not connection.

Browser other questions tagged

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