Implementation and use of finalize, dispose, and suppressfinalize in C #

Source: Internet
Author: User

Msdn recommends implementing the idisposable interface in the following mode:

public class Foo : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (!m_disposed)
{
if (disposing)
{
// Release managed resources
}

// Release unmanaged resources

m_disposed = true;
}
}

~Foo()
{
Dispose(false);
}

private bool m_disposed;
}

In fact, there are two functions used to release resources in the. NET object: dispose and finalize. Finalize is used to release unmanaged resources, while dispose is used to release all resources, including hosted and unmanaged resources.

In this mode, void dispose (bool
The disposing function uses a disposing parameter to determine whether it is currently called by dispose. If it is called by dispose (), it must be released at the same time.
Managed and unmanaged resources. If it is ~ Foo () (that is, the finalize () of C #) is called, you only need to release the unmanaged resources.

This is because the dispose () function is explicitly called by other code and requires resource release, while finalize is called by GC. In GC call
Other
Managed Objects may not need to be destroyed yet, and GC will call them even if they are to be destroyed. Therefore, you only need to release unmanaged resources in finalize. On the other hand
The managed and unmanaged resources have been released in dispose (). Therefore, it is unnecessary to call finalize again when the object is recycled by GC, so it is called in dispose ()
GC. suppressfinalize (this) prevents repeated calls to finalize.

However, even if you call finalize and dispose repeatedly, the resource is released only once because of the existence of the variable m_disposed. Excessive calls are ignored.

Therefore, the above mode ensures that:

1. Finalize only releases unmanaged resources;

2. Dispose releases managed and unmanaged resources;

3. It is no problem to repeatedly call finalize and dispose;

4. Finalize and dispose share the same resource release policy, so there is no conflict between them.

In C #, this mode needs to be implemented explicitly, where C #'s ~ The Foo () function represents finalize (). In C ++/CLI, this mode is automatically implemented, and the class destructor of C ++ are different.

According to the C ++ semantics, The Destructor is called when it is out of scope or delete. In managed C ++ (that is,. net
In C ++ managed in 1.1, the Destructor is equivalent to the finalize () method in Clr and called by GC during garbage collection. Therefore, the call time is unclear. In. net
In C ++/CLI of 2.0, the semantics of the Destructor is modified to the equivalent and dispose () method, which implies two things:

1. All the CLR classes in C ++/CLI implement the interface idisposable. Therefore, you can use the using keyword in C # To access the instances of this class.

2. destructor are no longer equivalent to finalize.

This is a good thing for the first point. I think in terms of semantics, dispose () is closer to C ++ destructor. For the second point, Microsoft made an extension by introducing "!". Function:

public ref class Foo
{
public:
Foo();
~Foo(); // destructor
!Foo(); // finalizer
};

"!" Function (I really don't know how to call it) is called by GC instead of finalize () in the original managed C ++. Msdn recommends that you write the following code to reduce code duplication:

~ Foo ()
{
// Release managed resources
This->! Foo ();
}

! Foo ()
{
// Release unmanaged Resources
}

For the above class, C ++/CLI generates the corresponding C # Code as follows:

Public class foo
{
Private void! Foo ()
{
// Release unmanaged Resources
}

Private void ~ Foo ()
{
// Release managed resources
! Foo ();
}

Public Foo ()
{
}

Public void dispose ()
{
Dispose (true );
GC. suppressfinalize (this );
}

Protected virtual void dispose (bool disposing)
{
If (disposing)
{
~ Foo ();
}
Else
{
Try
{
! Foo ();
}
Finally
{
Base. Finalize ();
}
}
}

Protected void finalize ()
{
Dispose (false );
}
}

Because ~ Foo () and! Foo () is not repeatedly called (at least Ms thinks so). Therefore, there is no variable identical to m_disposed in this Code, but the basic structure is the same.

In addition, we can see that it is not actually ~ Foo () and! Foo () is dispose and finalize, but a C ++/CLI compiler.
Two dispose
And finalize functions, and call them when appropriate. C ++/CLI has actually done a lot of work, but the only problem is that it depends on the user in ~ Foo ()
Yes! Foo ().

The last thing to mention about resource release is the close function. In terms of semantics, it is similar to dispose. According to msdn, this function is provided to make users feel more comfortable, because for some objects, such as files, you are more comfortable calling close ().

However, after all, these two functions do the same thing, so the code recommended by msdn is:

public void Close()
{
Dispose(();
}

Call the dispose function without parameters to obtain
The same semantics as dispose. This seems to be complete, but on the other hand, if both dispose and close are provided, it will bring some confusion to the user. No code found
Under the premise of details, it is difficult to know the differences between the two functions. Therefore, in the code design specification of. net, the two functions can only be used by users. Therefore, the recommended mode is:

Public class FOO: idisposable
{
Public void close ()
{
Dispose ();
}

Void idisposable. Dispose ()
{
Dispose (true );
GC. suppressfinalize (this );
}

Protected virtual void dispose (bool disposing)
{
// Same as before
}
}

An explicit implementation of void idisposable. Dispose () is used here (). This explicit implementation can only be accessed through interfaces, but cannot be accessed through implementation classes. Therefore:

Foo = new Foo ();

Foo. Dispose (); // Error
(FOO as idisposable). Dispose (); // correct

-------------------------------- The following is a summary of the previous expert in csdn ----------------------------------------------

1. The Finalize method (C # Is a destructor, hereinafter referred to as a destructor) is used to release unmanaged resources, and managed resources are automatically reclaimed by GC. Institute
We can also distinguish
Managed and unmanaged resources. All resources that will be automatically recycled by GC are managed resources, but those that cannot be automatically recycled by GC are unmanaged resources. When we directly use unmanaged resources in our classes
Less, so we basically don't need to write the destructor.

2. Most of the unmanaged resources will have many negative effects on the system. For example, if the database connection is not released, the available database connections in the connection pool may be exhausted. If the file is not closed, other processes cannot read and write the file.

Implementation Model:
1. Because most of the unmanaged resources require manual release, we should publish a method specifically to release the unmanaged resources. The dispose method that implements the idispose interface is the best model. Because C # supports using statements quickly, you can automatically call the dispose method when leaving the statement block.

2. Although you can manually release unmanaged resources, we still need to release the unmanaged Resources in the destructor. This is a secure application. Otherwise, if the programmer forgets to manually release the unmanaged resources due to negligence,
Then it will have disastrous consequences. Therefore, releasing unmanaged resources in destructor is a remedy, at least for most classes.

3. Because the calling of the Destructor will reduce the efficiency of GC in object collection, if you have completed the tasks of the Destructor (such as releasing unmanaged resources ), the suppressfinalize method should be used to tell GC that the destructor of an object does not need to be executed.

4. Only unmanaged resources can be released in the destructor, and no operations can be performed on any managed objects/resources. Because you cannot predict the running time of the destructor, when the Destructor is executed, the managed resources you operate on may have been released. This will cause serious consequences.

5. (This is a rule) If a class has a member that implements the idispose interface type and is created (note that it is created rather than received and must be created by the class itself) its instance object
This class should also implement the idispose interface and call the dispose method of all the members implementing the idispose interface in the dispose method.
Only in this way can we ensure that the dispose method of all objects that implement the idispose interface can be called, and that any resources that need to be released can be manually released.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.