157 suggestions for writing high-quality code to improve C # programs-recommendation 46: explicitly releasing resources must inherit the interface IDisposable,
Suggestion 46: The interface IDisposable must be inherited to explicitly release resources
Every type in C # represents a resource. There are two types of resources:
Managed resources: Resources allocated and released are managed by CLR, that is, new objects from CLR.
Unmanaged Resources: Objects not managed by CLR, such as Windows kernel objects, or files, database connections, sockets, and COOM objects.
If our type uses unmanaged resources, or we need to release managed resources explicitly, we need to have the type inheritance interface IDisposable, which is no exception. This is equivalent to telling the caller that type resources need to be displayed and released, and you need to call type Dispose methods.
A standard that inherits the type of the IDisposable interface should be implemented as follows. This implementation is called the Dispose mode:
Public class SampleClass: IDisposable {// demonstrate creating an unmanaged resource private IntPtr nativeResource = Marshal. allocHGlobal (100); // demonstrate creating a managed resource private AnotherResource managedResource = new AnotherResource (); private bool disposed = false; /// <summary> /// implement the Dispose method in IDisposable /// </summary> public void Dispose () {// it must be true Dispose (true ); // notify the garbage collection mechanism not to call the final generator (destructor) GC. suppressFinalize (this);} // <summary> // No It is necessary to provide a Close method only to better comply with the specifications of other languages (such as ///C ++) // </summary> public void Close () {Dispose () ;}/// <summary> /// required to prevent the programmer from explicitly calling the Dispose method. /// </summary> ~ SampleClass () {// It must be false Dispose (false );} /// <summary> // use protected virtual for non-sealed class modification // use private for sealing class modification /// </summary> // <param name = "disposing "> </param> protected virtual void Dispose (bool disposing) {if (disposed) {return;} if (disposing) {// clear managed resources if (managedResource! = Null) {managedResource. Dispose (); managedResource = null ;}// clear unmanaged resources if (nativeResource! = IntPtr. zero) {Marshal. freeHGlobal (nativeResource); nativeResource = IntPtr. zero;} // Let the type know that it has been released disposed = true;} public void SamplePublicMethod () {if (disposed) {throw new ObjectDisposedException ("SampleClass ", "SampleClass is disposed");} // omitted} class AnotherResource: IDisposable {public void Dispose (){}}
Inheriting the IDisposable interface also facilitates the implementation of syntax sugar using. For example:
Using (SampleClass cl = new SampleClass () {// omitted}
It is equivalent:
SampleClass cl; try {cl = new SampleClass (); // omitted} finally {cl. Dispose ();}
If two objects of the same type exist, using can also be used as follows:
Using (SampleClass c1 = new SampleClass (), c2 = new SampleClass () {// omitted}
If the two types are inconsistent, use the following method:
Using (SampleClass c1 = new SampleClass () using (SampleAnotherClass c2 = new SampleAnotherClass () {// omitted}