. NET Framework source code Research Series-delegate

Source: Internet
Author: User
Preface

Once upon a while, the source code of Microsoft products was just a fantasy, but now it has become a reality, and Microsoft finally opened its products to the outside world.Source codeIt is always a good thing to let us get a glimpse of the secrets of excellent products by throwing away the old-generation hatred between the open-source movement and Microsoft and the original intention of Microsoft.

Two days ago, I saw a comment in the essay, saying that he thought ". the Design Pattern in. NET is being discussed. the relationship between the Net Framework and the design pattern is actually not, but it reminds me that I have actually studied it. net Framework source code, so I am looking for time to share my experiences with you.

Today, let's start with the most confusing delegation, let's step into the. NET Framework source code world and learn together ExcellentProgramDesign.

Let's first look at the definition of delegation:Declares a reference type, which can be used to encapsulate naming or anonymous methods. The delegate is similar to the function pointer in C ++. However, the delegate type is safe and reliable.

I believe that after reading this passage, many people, including myself, will start exploring together.DelegateAndFunction pointerAs a result, a variety of web files appeared. But what is the delegated? Let's take a look at a simple section.Code:

 

  Public Delegate VoidOnaction (IntFlag );

Here we define the simplest delegate:Onaction.Msdn explanationDelegateClass is the base class of the delegate type, but only the system and compiler can explicitlyDelegateClass or multicastdelegate class derived. We can thinkOnactionYesfromDelegateInherited, but not explicitly inherited by the system.

Next, let's take a look at how Microsoft defines delegation:

 

  [Serializable ()]
[Classinterface (classinterfacetype. autodual)]
[System. runtime. interopservices. comvisible (True)]
Public Abstract ClassDelegate: icloneable, iserializable

It can be seen that delegate is an abstract class and implements the icloneable and iserializable interfaces, and has such an attribute as classinterface (classinterfacetype. autodual). This has many problems.

First,The delegate is an abstract class, so it must be inherited, but the delegate is the same as an integer., Is a type, so you can understand what to ask"Delegate Class is the base class of the delegate type, but only the system and compiler can explicitlyDelegateClass or multicastdelegate class is derived. Because it is impossible to inherit a subclass from an integer, why is the delegate a class and a structure like an integer? The answer to this question is as follows.

Secondly, this is what I don't think I understand. The delegate implements the icloneable and iserializable interfaces, that is, the delegate can be cloned and serialized. I believe no one will write it.Onaction. Clone ();In this sentence. it is a bit confusing to clone a delegate on a superficial layer. however, if you can explain why the icloneable interface is used in advance with good programming habits, delegate the implementation of iserializable is even more confusing, because it may lead to some inexplicable compilation errors. I have encountered a bug where a single-piece entity class marked for serialization contains an event (the event implements iserializable by default ), when this event causes serialization, all the information related to the event's reference is returned.Unlabeled serializationThe final solution is to mark the event as [nonserialized].

The following describes how to implement delegation:

 

Code

    Public     Abstract     Class  Delegate: icloneable, iserializable
{
// Object To be called
Internal Object _ target;

// Methodbase, either cached after first request or assigned from a dynamicmethod
Internal Methodbase _ methodbase;

// _ Methodptr is a pointer to the method we will invoke
// It cocould be a small thunk if this is a static or um call
Internal Intptr _ methodptr;

// In the case of a static method passed to a delegate, this field stores
// Whatever _ methodptr wocould have stored: And _ methodptr points to
// Small thunk which removes the "this" pointer before going on
// To _ methodptraux.
Internal Intptr _ methodptraux;

// This constructor is called from the class generated by
// Compiler generated code
Protected Delegate (object target, string method)
{
If (Target = Null )
Throw New Argumentnullexception ( " Target " );

If (Method = Null )
Throw New Argumentnullexception ( " Method " );

// This API existed in V1/V1.1 and only expected to create closed
// Instance delegates. constrain the call to bindtomethodname
// Such and don't allow relaxed Signature Matching (which cocould make
// The choice of target method ambiguous) for backwards
// Compatibility. The name matching was case sensitive and we
// Preserve that as well.
If ( ! Bindtomethodname (target, type. gettypehandle (target), method,
Delegatebindingflags. instancemethodonly |
Delegatebindingflags. closeddelegateonly ))
Throw New Argumentexception (environment. getresourcestring ( " Arg_dlgttargmeth " ));
}

// This constructor is called from a class to generate
// Delegate based upon a static method name and the type object
// For the class defining the method.
Protected Unsafe Delegate (Type Target, string method)
{
If (Target = Null )
Throw New Argumentnullexception ( " Target " );

If ( ! (Target Is Runtimetype ))
Throw New Argumentexception (environment. getresourcestring ( " Argument_mustberuntimetype " ), " Target " );

If (Target. isgenerictype && Target. containsgenericparameters)
Throw New Argumentexception (environment. getresourcestring ( " Arg_unboundgenparam " ), " Target " );

If (Method = Null )
Throw New Argumentnullexception ( " Method " );

// This API existed in V1/V1.1 and only expected to create open
// Static delegates. constrain the call to bindtomethodname to such
// And don't allow relaxed Signature Matching (which cocould make
// Choice of target method ambiguous) for backwards compatibility.
// The name matching was case insensitive (no idea why this is
// Different from the constructor above) and we preserve that
// Well.
Bindtomethodname ( Null , Target. typehandle, method,
Delegatebindingflags. staticmethodonly |
Delegatebindingflags. opendelegateonly |
Delegatebindingflags. caselessmatching );
}

// Protect the default constructor so you can't build a delegate
Private Delegate ()
{
}

The code above shows that the delegate class contains four fields of the internal type. From its annotation, we can see that _ target is the object we want to call, and _ methodbase is the method passed when assigning values to the delegate, _ methodptr is a pointer to this method. _ methodptraux is the same as the content pointed to by methodptr of the static type delegate, but the object reference is missing. when we look at the three constructor functions of the delegate class, one is private and used to prevent instantiation. The other two functions are similar. What we do is to bind a method to an object. the method here should be the method we assign to the delegate, and the object is the object maintained by the compiler itself. here, a method bindtomethodname is called. The implementation is not visible in the source code, but the following content can be seen:

  [Methodimplattritions (methodimploptions. internalcall)]
Private Extern BoolBindtomethodname (object target, runtimetypehandle methodtype, string method, delegatebindingflags flags );

The methodimplattribute label indicates that the method is a CLR internal method. We do not know what it is. There are many other such methods, so we will not mention them one by one. When talking about this, we can find"OnactionYesfromDelegateInherited "and"DelegateThe class is the base class of the delegate type. The correct understanding should beThe delegate class internally manages an object for binding methods.This can also be seen from the constructor decompiled by onaction:

Code

  . Method  Public  Hidebysig specialname rtspecialname
Instance Void . Ctor ( Object ' Object ' ,
Native Int ' Method ' ) Runtime managed
{
} // End of method onaction:. ctor

In addition, there is a static method in delegate:

Public static delegate createdelegate (type, object firstargument, methodinfo method, bool throwonbindfailure)

There are 11 reloads before and after the method, and the method body does not include:

 

Code

  Delegate d  = Internalalloc (type. typehandle );
If ( ! D. bindtomethodinfo (firstargument, method. methodhandle, method. declaringtype. typehandle,
Delegatebindingflags. relaxedsignature ))
{
If (Throwonbindfailure)
Throw New Argumentexception (environment. getresourcestring ( " Arg_dlgttargmeth " ));
D = Null ;
}

Such a piece of code. internalalloc, bindtomethodinfo, and bindtomethodname belong to the internal CLR method. I can't see what it is, but I can only roughly guess that the CLR has generated a delegate object internally, and then submit the defined delegate signature, method, method reference, and other content to the delegate class for maintenance.

 

Through the above analysis, we found that, for its definition, the delegate is essentially a class, and its responsibility is to replace our management and maintenance method call. all of this is not related to function pointers, whether it is a function or an external function. so far, I believe everyone has a different understanding of Delegate. At the same time, we also found that C # is just a layer of CLR shell and does not involve much core content.

 

 

 

 

The above is just my personal opinion. Due to my limited level, it is inevitable that I have an incorrect understanding. If you have better opinions, please correct me.

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.