.net’s GC mechanism has two problems: First, GC cannot release all resources, and it cannot release unmanaged resources. Secondly, GC is not real-time, and all GCs are uncertain.
In order to solve this problem donet provides a destructor
public class TestClass: System.IDisposable
{
//Dispose method for programmers to explicitly call
public void Dispose()
{
//Call the Dispose method with parameters to release managed and unmanaged resources
Dispose(true);
// Manually call Dispose to release resources, then the destructor is unnecessary, here to prevent the GC from calling the destructor
System.GC.SuppressFinalize(this);
}
//The protected Dispose method is guaranteed not to be called externally.
//Pass in bool value disposing to determine whether to release managed resources
protected void Dispose(bool disposing)
{
if (disposing)
{
///TODO: Add the code for cleaning up "managed resources" here, it should be xxx.Dispose();
}
///TODO: Add the code to clean up "unmanaged resources" here
}
//Destructor function for GC call
~TestClass()
{
Dispose(false);//Release unmanaged resources
}
}
And even if we forget to call Dispose at the right time, GC will help us clean up unmanaged resources when releasing objects. The role played by the GC is only a guarantee, it should play this role, and we cannot rely on it too much. In fact, we should manually call GC.Collect for garbage collection in time when the larger module exits.
Why objects of classes that implement the IDisposable interface, because the .net CLR uses the GC (garbage collector) mechanism to manage memory, not like the C++ language, it can ensure that the destructor of the object is It is always called automatically. Sometimes if the conditions for starting the GC are not met during the running of the program, the GC may not be started even once. In this way, if a class needs to occupy important resources, it should implement the IDisposable interface, or use another simple way: Using Using, such as:
Using(MyClass myObj = new MyClass())
{ … }
For those that do not implement the IDisposable interface, there is no Dispose method, but their Finalize also cannot be guaranteed to be called.
Using(MyClass myObj = new MyClass())
{ … }
is a good method, but only if MyClass implements the IDisposable interface Write like this.
IDispose mode is used a lot in C++ to clean up resources. In C#, resources are divided into managed and unmanaged. Managed resources are C#’s CLR helps us clean up. It is the object release work done by calling the object’s destructor. For unmanaged systems, we need to release it ourselves. For example, database connection objects, which require us to manually call Its Dispose() method is used to release the object. In fact, we don’t know what the content of Dispose() does. Of course, this is object-oriented. It doesn’t want you to deal with the details of the implementation, huh!
For us developers, after understanding how it is used, they will always be interested in how it is implemented. Below, I will show the code that implements the IDispose mode in C#, and everyone will learn together Now, in fact, it is used in many occasions. When we manually encapsulate the website and database, we will use it. Let’s take a look at the code:
< pre> ///
/// Implement IDisposable and recover resources from unmanaged systems
///
public class IDisplosePattern: IDisposable
{
public void Dispose()
{
this.Dispose(true);////Release managed resources
GC.SuppressFinalize(this);//Request the system not to call the finalizer of the specified object. //This method sets a bit in the object header, and the system will check this bit when calling the finalizer
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)//_isDisposed is false means no manual dispose
{
if (disposing)
{
//Clean up managed resources
}
//Clean up unmanaged resources
}
_isDisposed = true;
}
private bool _isDisposed;
~IDisplosePattern()
{
this.Dispose(false);//Release unmanaged resources, managed resources are completed by the ultimate device itself
}
}
Through the above code, we know that for the managed system (C#’s CLR is managed by us), it is released directly through the ~IDisplosePattern() method , And when the ~IDisplosePattern() method is called, we don’t know, because it is called by the CLR to help us, and when we manually dispose the method, it will call the dispose(true) overload method, it Will help us clean up managed and unmanaged resources, as shown in the figure:
p> p>
public class TestClass: System.IDisposable
{
//Dispose method for programmers to explicitly call
public void Dispose()
{
//Call the Dispose method with parameters to release managed and unmanaged resources
Dispose(true);
// Manually call Dispose to release resources, then the destructor is unnecessary, here to prevent the GC from calling the destructor
System.GC.SuppressFinalize(this);
}
//The protected Dispose method is guaranteed not to be called externally.
//Pass in bool value disposing to determine whether to release managed resources
protected void Dispose(bool disposing)
{
if (disposing)
{
///TODO: Add the code for cleaning up "managed resources" here, it should be xxx.Dispose();
}
///TODO: Add the code to clean up "unmanaged resources" here
}
//Destructor function for GC call
~TestClass()
{
Dispose(false);//Release unmanaged resources
}
}
///
/// Implement IDisposable and recover resources from unmanaged systems
///
public class IDisplosePattern: IDisposable
{
public void Dispose()
{
this.Dispose(true);////Release managed resources
GC.SuppressFinalize(this);//Request the system not to call the finalizer of the specified object. //This method sets a bit in the object header, and the system will check this bit when calling the finalizer
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)//_isDisposed is false means no manual dispose
{
if (disposing)
{
//Clean up managed resources
}
//Clean up unmanaged resources
}
_isDisposed = true;
}
private bool _isDisposed;
~IDisplosePattern()
{
this.Dispose(false);//Release unmanaged resources, managed resources are completed by the ultimate device itself
}
}