What is the difference between implementations of IDisposable?

7

I confess that I still do not understand everything about manipulating the destruction of an object in C # and now, when testing Visual Studio 2015 Preview , when implementing a class I have included the inheritance of IDisposable and I used the Implement interface with Dispose pattern option.

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 could not understand these comments with TODOs on the finalizer ~DBConnection() method, on GC.SuppressFinalize(this); , and on Dispose(bool disposing) and all its contents ...

Looking at other options, I saw the following implementation:

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

Of course, we have the following:

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

What I would implement as it is usually shown in web examples:

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

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

Can anyone help me understand the difference between these methods and the first method's comments?

    
asked by anonymous 24.06.2015 / 03:00

2 answers

2

Several things. I'm going to translate the first piece of code to get 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 are managed and unmanaged objects.

  • Managed objects are those that are being handled directly by garbage collector . That is, class objects in your system are usually managed ;
  • unmanaged objects are the converse. A database provider , for example, written in a non-.NET DLL. Such objects usually have their own memory release procedure specified by the technology provider.

Within if you should place any and any additional code that will allow immediate release of machine resources. Zero large variables in memory, for example.

In the unmanaged part of the part of the unmanaged feature you should put any code that involves resource usage that .NET does not have any control, printer> or a disk controller. In a database context, close the connection, (which uses a socket that is not .NET, but is connected to .NET code).

The idea of this destructor:

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

Avoid any automatic memory releases by garbage collector . You tell the garbage collector that your code will coordinate the destruction of the object.

Let's return to the example of slow buffers (disks and printers). Connecting to the controllers takes time. If you release the object before, you lose the reference to communicate with the controller and ensure everything is done right. This is critical when you need to run, for example, some flush . Releasing the object before can cause the communication to be interrupted and some problem of inconsistency between the parties in the communication is caused.

A socket database is a classic case of this. Closing the connection is recommended to be done after 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 should ensure that the object exists as long as possible to avoid problems.

After some time, the garbage collector will do routine checks and, upon verifying that the object no longer has references, will delete the object. This is safer than asking for immediate release of the object.

    
24.06.2015 / 18:27
-1

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

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

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

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

From period to period, GB recycles to see if objects in the heap memory are being used by the application and perform operations to clear them from memory.

Dispose Pattern then develops conceptual and practical ways to manage these "disposables" objects by forcing them to "wipe" out of memory or by deleting the automatic delete request from memory.

    
24.06.2015 / 03:21