What does '~' mean in front of the constructor of a C #

31

Working on a project here in the company, I came across some commands that are now being used the most ( yield , ?? , anonymous type ) but until I understood, but one that caught my attention because I did not know the what is.

Has anyone seen the following example?

public Perfil {
    public ICollection<Usuario> Usuarios { get; set; }
    ...

    ~Perfil() {
        Usuarios = new HashSet<Usuarios>();
    }
}

Who ever saw and knows about it, could you give a brief explanation? It's just curiosity to understand better.

Are there other similar ones?

    
asked by anonymous 12.03.2014 / 20:56

2 answers

23

This is not a constructor, but a destructor.

The destructor is called when the CLR checks that there are no more references to the object, and then it will delete it from memory. If a destructor is declared in the object class, then the object will be called to clear the object before the memory is returned to the system.

Now, speaking of your example, it is not making much sense. Generally, in the destructor, cleanup of non-managed resources is done ... but in the example a new object is being created, which may even make sense given the complete context, but it is in a way a very "suspicious" .

    
12.03.2014 / 21:01
13

This is a destructor. The syntax is inherited from C ++. But the semantics are quite different.

In practice, destructors do not exist in language. To understand I will explain two other concepts.

Dispose

This is a method available in all types that implement the IDisposable interface and allows resources to be freed when the object is no longer needed. The call of Dispose() can be done manually at any time or automatically using statement using . The release of resources are free memory. Only the garbage collector allows you to free the memory. If a type does not need external resources, it is unnecessary.

Finalize

This is the method that actually processes everything that is needed the moment before the memory release. We can say that it is responsible for the release, although the one who does this is the garbage collector . A finalize() is always available, because it is part of type Object and in most cases the default implementation of Object is sufficient.

Destroyer

You can not override a Finalize() method on its type. The compiler does not allow you to use your own implementation. But it allows the destructor to be created. And it can process what you want in the destructor and call the Finalize() . The default implementation of Finalize must be available in all types.

Then the code

class Car {
    ~Car() { // destrutor
        // código de limpeza...
    }
}

is the same as

protected override void Finalize() {
    try {
        // código de limpeza...
    } finally {
        base.Finalize();
    }
}

but the second form can only be generated by the compiler instead of the destructor.

So a C # destructor does not run right after the object is no longer needed, nor is it executed in the same thread , but in the thread garbage collector . There are a number of problems related to the finalization method that are not part of the scope of the question. Finalizers, even in the form of a destructor, should only be customized when the programmer fully understands all its implications.

I've placed it on GitHub for future reference.

    
02.06.2014 / 16:10