The entrusted learning notes of C # Advanced Programming (reproduced)

Source: Internet
Author: User

Full Digest from

Http://www.cnblogs.com/xun126/archive/2010/12/30/1921551.html

Well written, deliberately backed up! and correct the error code.

Body:

Recently Learning C # commissioned, through the network of information and books, now summarized as follows:

The callback (Callback) function is an important part of Windows programming. The callback function is actually a pointer to a method call and also a function pointer, a very powerful programming

The callback (Callback) function is an important part of Windows programming. The callback function is actually a pointer to a method call and a function pointer, which is a very powerful programming feature. NET implements the concept of a pointer to a function in the form of a delegate. is different from the function pointer of C + +. NET delegate is type-safe. In other words, the function pointer of a C + + is simply a pointer to a memory unit, and we cannot know what the pointer actually points to, such as parameters and return types.

A delegate is required when the method is passed to other methods. Consider the following function:

C++:

#include <iostream>

#include <string>

using namespace Std;

int fun (int);

int fun_call (int (*f) (int), int);

void Main (int argc,char* argv[])

{

typedef int (*FP) (int);

FP FPT;

Fpt=fun;

Count<<fun_call (fpt,1);

}

int fun (int a)

{

return A-1;

}

int fun_call (int (*FP) (int), int b)

{

Return (FP (+) +b);

}

The "Ftp=fun" of the above program implements the initialization of the function pointer, assigns the fun address to the function pointer ftp directly, then transmits to the fun_call,fun_call can calculate the result according to these two parameters: FP (10) =9,9+1=10. The method is implemented to transfer the methods to other methods.

function pointers are most commonly used to call functions in bulk using an array of function pointers:

int F1 () {return 1;}

int F2 () {return 2;}

int F3 () {return 3;}

void Main (int argc,char* argv[])

{

tpyedef Int (* fp) ();

FP FPS[3]={F1,F2,F3};

for (int 0;i<2;i++)

{

cout<<fps[i]<<endl; Implementing calling functions by array sequence number

}

}

At compile time we do not know what the second method will be, this information can only be obtained at runtime, so we need to pass the second method as a parameter to the first method. Only the address of the function can be extracted and routed to a single parameter in C + +. C is no type-safe, and any function can be passed to a method that requires a function pointer. This direct approach leads to problems such as type safety, which is rarely isolated in object-oriented programming, and is typically associated with a class instance prior to invocation. This method of pointers does not take into account this situation. So. NET is syntactically not allowed to use this straightforward method. If you are passing a method, you must encapsulate the details of the method in a new type of object, the new object being the delegate.

  A delegate, in fact, is just a special type of object, and what is special is that all the objects we defined earlier contain data, and the delegate contains only the address of the function.

1. Declaring a delegate in C #

delegate void Method (int x);

Defining a delegate means telling the compiler what type of method a delegate of this type represents, and then creating one or more instances of the delegate. The compiler will create a class representing the delegate in the background. That is, defining a delegate is basically defining a new class, so you can define the delegate anywhere in the definition class, either inside the class or outside the class. Note that the delegate is of very high type security, so when defining a delegate, you must give all the details of the method signature and return type that it represents.

2. Using delegates in C #

Using System;

Namespace Delegatespace

{

Class DelegateTest

{

Private delegate string GetString (int x,int y);

static void Main ()

{

Test test=new test ();

GetString method=new GetString (test. ADD);

Console.WriteLine (Method ());

}

}

Class Test

{

public string Add (int x,int y)

{

Return (x+y). ToString ();

}

}

}

The above program declares a delegate of type GetString and initializes it to the method add (int x,int y) that points to the object test. In C #, a delegate is always syntactically a constructor with a parameter, which is the method that the delegate points to, which must match the signature at the time the delegate was originally defined. As in the example above, the delegate is defined as: "Delegate string GetString ();" The return type of the function requiring the delegate is string if test. ADD (int x,int y) returns an int, the compiler will error. Also pay attention to the assignment statement: "GetString method=new GetString (test. ADD); " cannot be written as "GetString method=new GetString (test. ADD (3,2)); " Because Test. ADD (2,3) returns a string. The constructor of the delegate needs to pass in the address of the function, which is much like the function pointers in C/s + +.

3. Multicast delegation

The number of calls to the delegate is the same as the number of times the method was called, and if multiple methods are to be called, the delegate needs to be explicitly called multiple times. A delegate can also contain multiple methods. This delegate is called a multicast delegate. If you call a multicast delegate, you can call multiple methods sequentially consecutively. therefore, the signature of the delegate must return void, otherwise, only the result of the last method invoked by the delegate is obtained.

Such as:

delegate void Doubleop (double value);

Class Mainentry

{

static void Main ()

{

Doubleop Operations=mathoperation.multiplybytwo;

Operations+=mathoperation.square;

}

}

Class Mathoperation

{

public static double Multiplybytwo (double value)

{

return value*2;

}

public static double Square (double value)

{

return value*value;

}

}

Above "Doubleop operation=mathoperation.multiplybytwo;operation+=mathoperation.square;" is equivalent to "DoubleOp operation1= Mathoperation.multiplybytwo;doubleop Operation2=mathoperation.square;doubleop operations=operation1+operation2; " , the multicast delegate can also recognize the operator-and-=, which is used to remove a method call from a delegate.

There is a big problem with calling multiple methods with one multicast delegate. The multicast delegate contains a collection of call-by-delegate delegates. If a method is called by a delegate to throw an exception, the entire iteration terminates. In this case, to avoid this problem, you should manually iterate through the list of methods. You can use the method defined by the delegate class Getinvocationlist (), which returns an array of Delegate objects.

Consider the following code:

public delegate void Demodelegate ();

Class Program

{

static void One ()

{

Console.WriteLine ("One");

throw new Exception ("test!");

}

static void ()

{

Console.WriteLine ("both");

}

static void Main ()

{

Demodelegate Dl=one;

Dl+=two;

Try

{

DL ();

}

catch (Exception)

{

Console.WriteLine ("Exception caught!");

}

}

}

Operation Result:

One

Exception caught!

The modified code is as follows:

static void Main ()

{

Demodelegate Dl=one;

Dl+=two;

Delegate[] Delegates=dl. Getinvocationlist ();

foreach (demodelegate D in Delegates)

{

Try

{

D ();

}

catch (Exception)

{

Console.WriteLine ("Exception caught");

}

}

       

}

The results of the operation are as follows:

One

Exception caught

Both

  Similarly, if the delegate signature does not return void, but wants to get all the results after the delegate invocation, you can also use getinvocationlist () to get an array of delegate objects, and then use the above iteration to get the return result.

4. Anonymous method

There is another way to use delegates: through anonymous methods. An anonymous method is a block of code that is used as a delegate parameter.

The following code:

Using System;

Namespace DelegateTest

{

Class Program

{

Delegate String delegatestring (string val);

static void Main ()

{

String mid= ", middle part";

            Delegatestring anondel=delegate (string param)

{

Param+=mid;

param+= "and End";

return param;

};

Console.WriteLine (Anondel ("Strat of string");

}

}

}

The code block uses the method-level string variable, mid, which is defined outside the anonymous method and added to the parameter to be passed, and the code returns the string value. The advantage of an anonymous method is that it reduces the code to be written. You do not have to define a method that is used only by delegates. This is obvious when you define a delegate for an event. this helps to reduce the complexity of the code, especially when several events are defined, and the code is relatively straightforward. When you use anonymous methods, the code executes not too quickly.

  There are a few rules that you must follow when using anonymous methods:

1) In an anonymous method, you cannot use a jump statement to jump outside of the anonymous method;

2) The external jump statement of the anonymous method cannot jump to the inside of the anonymous method;

3) You cannot access unsafe code inside an anonymous method or access the ref and out parameters that are used outside of an anonymous method, but you can use other variables that are defined outside the anonymous method.

5.lambda expression

This is a new method that C # 3.0 provides for anonymous methods. As in the preceding statement:

...

static void Main ()

{

String mid= ...;

    Delegatestring anondel=param=>

{

Param+=mid;

param+= "and End";

return param;

};

    ...

}

...

  The lambda expression = = to the left of the anonymous method to list the parameters required, the implementation code is listed on the right, implementation code in curly braces, similar to the previous anonymous method, if the implementation code only one row, you can delete the curly brace and return statement, the compiler will automatically add the statement.

such as: public delegate bool Predicate (int val);

predicate pl=x=>x>5;

In the lambda expression above, the variable x is defined on the left, and the type of the variable is automatically set to int, because this is defined by the delegate, and the implementation code returns a comparison of x>5 Boolean results. Returns True if X is greater than 5, otherwise false is returned.

6, covariant and anti-change

The method called by the delegate does not need to be the same as the definition type of the delegate declaration. This results in covariant and anti-change.

1) return type covariance

The return type of the method can be derived from the type of the delegate definition. The following code:

public class Delegatereturn

{

}

public class Delegatereturn2:delegatereturn

{

}

Public delegate Delegareturn MyDelegate1 ();

Class Program

{

static void Main ()

{

MyDelegate1 d1=method1;

D1 ();

}

Static DelegateReturn2 Method1 ()

{

DELEGATERETURN2 d2=new DelegateReturn2 ();

return D2;

}

}

In the preceding code, the delegate mydelegate is defined as the return Delegatereturn type. The method that gives the delegate instance D1 returns the DelegateReturn2 type, DelegateReturn2 derives from delegate, and satisfies the requirement of the delegate according to the subclass "is" the parent class. This is called the covariance of the return type.

2) parameter type of the resistance variable

A delegate-defined parameter may be different from a method called by a delegate, which is different from the return type, because the type of the parameter used by the method may derive from the type defined by the delegate. The following code:

public class Delegateparam

{

}

public class Delegateparam2:delegateparam

{

}

public delegate void MyDelegate2 (DelegateParam2 p);

Class Program

{

static void Main ()

{

MyDelegate2 d2=method2;

DelegateParam2 p=new DelegateParam2 ();

D2 (P);

}

static void Method2 (Delegateparam p)

{

}

}

In the preceding code, the argument type used by the delegate is DelegateParam2, and the method that gives the delegate instance D2 uses the parameter type Delegateparam,delegateparam is the base class for DelegateParam2.

The entrusted learning notes of C # Advanced Programming (reproduced)

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.