C # interface

Source: Internet
Author: User

Because the CLR does not support multiple inheritance, it provides a "shrinking version" of multiple inheritance through the interface

And the inherited and derived formats differ from C + +

1. In C + +, if a function of the base class is virtual, the function with the same declaration and name in the inheriting class defaults to the virtual function corresponding to the base class

2, in C #, you must precede the method of the derived class with the override prefix to be considered a virtual method, otherwise it is considered to be a separate method of the inheriting class, it has nothing to do with the base class, and the method also overwrites the virtual method of the base class with the same name. So at this point, a new prefix is generally used to indicate that this method is a separate implementation of the inherited class.

C # and the CLR allow a class to inherit multiple interfaces, and of course all inherited interface methods must implement

Interfaces allow you to define events, no parameters, and parameter attributes, but you cannot define any construction methods and instance fields

If the method of the interface is not marked as virtual, the compiler will tag virtual and sealed for it, which will prevent the derived class from overriding the interface method. If marked as virtual, you can override the interface method in the inheriting class

One example here is the Dispose method that implements the IDisposable interface

Because resources are divided into managed and unmanaged resources

Managed resources include reference class objects that are allocated on the heap, and so on

Unmanaged resources include files, window handles, streams, kernel objects, socket objects, and so on

The garbage collection area can only automatically reclaim managed resources and not reclaim unmanaged resources, which can only be released together at the end of a process if these unmanaged resources are not collected manually, and the mechanism for reclaiming unmanaged resources is through IDisposable.

However, this is not so simple, a standard inherits the type of IDisposable interface should be implemented as follows. This implementation we call the Dispose pattern:

Public ClassSampleclass:idisposable
{
//Demo Creating an unmanaged resource
PrivateIntPtr Nativeresource=Marshal.allochglobal (100);
//Demo Creating a managed resource
PrivateAnotherresource Managedresource= NewAnotherresource ();
Private boolDisposed= False;

/// <summary>
///Implementing the Dispose method in IDisposable
/// </summary>
Public voidDispose ()
{
//Must be True
Dispose (True);
//Notifies the garbage collection mechanism not to call finalizers (destructors)
Gc. SuppressFinalize (This);
}

/// <summary>
///Not necessary, provide a close method just to be more compliant with other languages (such as C + +) specification
/// </summary>
Public voidClose ()
{
Dispose ();
}

/// <summary>
///Must, in case the programmer forgets to explicitly call the Dispose method
/// </summary>
~SampleClass ()
{
//Must be false
Dispose (False);
}

/// <summary>
///Protected virtual for non-sealed class modification
///Seal class decoration with private
/// </summary>
/// <param name= "disposing" ></param>
Protected Virtual voidDispose (boolDisposing
{
If(disposed)
{
Return;
}
If(disposing)
{
//Clean up Managed resources
If(Managedresource!= Null)
{
Managedresource.dispose ();
Managedresource= Null;
}
}
//Cleanup of unmanaged Resources
If(Nativeresource!=IntPtr.Zero)
{
Marshal.freehglobal (Nativeresource);
Nativeresource=IntPtr.Zero;
}
//Let the type know that they have been released
Disposed= True;
}

public void Samplepublicmethod ()
{
if ( Disposed)
{
throw New ObjectDisposedException ( " sampleclass " "sampleclass is Disposed" );
}
// omit
}
}

In Dispose mode, almost every line has a special meaning.

In the standard dispose mode, we notice a method that begins with a ~:

<summary>
must, in case the programmer forgets to explicitly call the Dispose method
</summary>
~SampleClass ()
{
must be false
Dispose (false);
}

This method is called a type terminator. The whole point of providing a finalizer is that we cannot expect the caller of the type to be actively invoking the Dispose method, based on the fact that the finalizer is called by the garbage collector, and the finalizer is used as a remedy for resource release.

A type of Dispose method should allow multiple calls without throwing exceptions. For this reason, the type internally maintains a private Boolean variable disposed:

private bool disposed = false;

In the actual method of handling code cleanup, add the following judgment statement:

if (disposed)
{
return;
}
omit the code for the Cleanup section and assign a value of disposed to true at the end of the method
disposed = true;

This means that if a type is cleaned up once, the cleanup will no longer work.

It should be noted that in the standard Dispose mode, the Dispose method that really implements the IDisposable interface does not have actual cleanup work, it actually calls the following protected virtual method with a Boolean parameter:

/// <summary>
/// non-sealed class decoration with protected virtual
/// sealed class decoration with private
///</summary>
///< Span style= "COLOR: #008000" > <param name= "disposing" ></param>
protected virtual void Dispose (bool disposing)
{
// omit code
}

The reason for providing such a protected virtual method is to take into account the fact that this type is inherited by other classes. If a type has a subclass, the subclass might implement its own dispose pattern. A protected virtual method is used to remind subclasses that they must notice the cleanup of the parent class when implementing their own cleanup method, that is, the subclass needs to call base in its own release method. Dispose method.

Also, we should have noticed that the virtual method that actually writes the resource release code is with a Boolean parameter. This parameter is provided because we treat managed and unmanaged resources differently when the resource is released.

The call parameter is true in the parameterless Dispose method for the explicitly freed resource that is called by the caller:

Public void Dispose ()
{
must be True
Dispose (true);
other omitted
}

This indicates that the code should handle both the managed and unmanaged resources at this time.

In the finalizer for an implicit cleanup resource that is called by the garbage collector, the calling parameter is false:

~SampleClass ()
{
must be false
Dispose (false);
}

This indicates that when an implicit cleanup is available, the unmanaged resources are processed as long as they are handled.

So why treat managed and unmanaged resources differently. Before we elaborate on this, we need to understand first: does the managed resource need to be cleaned up manually? You might want to first divide the types in C # into two categories, one inheriting the IDisposable interface, and one without inheritance. The former, which we call a non-trivial type for the time being, is called the normal type. Non-trivial type because it contains an unmanaged resource, it needs to inherit the IDisposable interface, but this contains the unmanaged resource's type itself, which is a managed resource. So does the managed resource need to be cleaned up manually? The answer to this question is that the normal type in the managed resource does not need to be cleaned manually, rather than the normal type, which needs to be cleaned manually (that is, the Dispose method is called).

The idea of the Dispose pattern design is based on: if the caller explicitly calls the Dispose method, then the type should be programmed to release all resources. If the caller forgets to call the Dispose method, then the type assumes that all of its managed resources (even those of the non-trivial type described in the previous paragraph) are all handed over to the garbage collector for recycling without manual cleanup. With this in mind, we understand why the parameter passed by the virtual method in the Dispose method is true, and the parameter passed in by the virtual method is false in the finalizer.

In practice, we can display the call to Dispose method through the try...finally statement, or we can call the Dispose method implicitly through the using statement, which is the same, and the compiler also translates the using statement into the Try...finally form.

using New Font ("Arial"10.0f)) {    byte charset = font1. gdiCharSet;}

is actually

{  new Font ("Arial"10.0f);   Try   {    byte charset = font1. gdiCharSet;  }   finally   {    ifnull)      ((IDisposable) font1). Dispose ();  }}

In WinForm, the form class that is often used is also inherited from the IDisposable interface, so it also implements the Dispose method, and VS automatically generates protected override void Dispose (bool disposing) The implementation of the method, as follows

        /// <summary>        ///clean up all the resources that are in use. /// </summary>        /// <param name= "disposing" >true if the managed resource should be disposed, otherwise false. </param>        protected Override voidDispose (BOOLdisposing) {            if(Disposing && (Components! =NULL) ) {components.            Dispose (); }            Base.        Dispose (disposing); }

Therefore, when instantiating a form class object, the new in the using statement

The principle of choosing a base class or an interface

1, is-a contrast can-do

If the derived class and the base class cannot establish a is-a relationship, use the interface instead of the base class, and the interface implies a can-do relationship that represents some functionality that can be implemented if the class needs to implement these functions

2. Ease of Use

The base analogy interface should be easy. Because the interface must implement all methods, and the base class already has the default implementation of the method, after inheriting the base class, only need to modify the method that does not need the default action

3. Version control

Add a new method to the basis function class, and if you keep the original method intact, you will not be using the image or recompiling the code. If you add a new method to the interface, you must re-implement the interface in the current code and compile it.

Therefore, try to use the base class, if the base class is not satisfied, consider adding an interface

C # interface

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.