C # advanced programming-commissioned study notes,

Source: Internet
Author: User

Entrusted learning notes for C # advanced programming (reproduced ),
Full text excerpt

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

 

Well written, specially backed up! Correct the error code ..

 

Body:

Recently commissioned by C #, the documents and books on the Internet are summarized as follows:

The Callback function is an important part of windows programming. A callback function is actually a method call pointer and also a function pointer. It is a very powerful programming feature.

The Callback function is an important part of windows programming. A callback function is actually a method call pointer and also a function pointer. It is a very powerful programming feature .. NET implements the function pointer concept in the form of delegation. Unlike C/C ++ function pointers, the. NET delegate is type-safe. That is to say, the C/C ++ function pointer is just a pointer to a memory unit. We cannot know what the pointer actually points to, such as parameters and return types.

Delegate is required when a method is sent to another method. Consider the following functions:

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)

{

Return A-1;

}

Int fun_call (int (* fp) (int), int B)

{

Return (fp (10) + B );

}

The above-mentioned "ftp = fun" program initializes the function pointer, directly assigns the fun address to the function pointer ftp, and then transfers it to fun_call. fun_call can calculate the result based on these two parameters: fp (10) = 9, 9 + 1 = 10. The method is transferred to other methods.

The most common function pointer is to use a function pointer array to call functions in batches:

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; // call a function by array serial number

}

}

During compilation, we do not know what the second method will be. This information can only be obtained at runtime. Therefore, we need to pass the second method as a parameter to the first method. In C/C ++, only the function address can be extracted and transmitted as a parameter. C has no type security. You can transmit any function to a method that requires a function pointer. This direct method will cause some problems, such as type security. In object-oriented programming, methods are rarely isolated and usually need to be associated with class instances before calling. This pointer method does not consider this situation. Therefore,. NET syntax does not allow this direct method. To pass a method, you must encapsulate the details of the method in a new type of object. This new object is the delegate.

Delegation is actually only a special object type. In particular, all the objects we previously defined contain data, and the delegate only contains the address of the function.

1. Declare the delegate in c #

Delegate void Method (int x );

Defining a delegate means telling the Compiler which type of delegate represents, and then creating one or more instances of the delegate. The compiler creates a class that indicates the delegate in the background. That is to say, defining a delegate is basically to define a new class. Therefore, you can define the delegate wherever the class is defined, either inside the class or outside the class. Note that a delegate has high type security. Therefore, when defining a delegate, you must provide all the details such as the method signature and return type it represents.

2. Use delegation 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 the delegate of the type GetString and initializes it so that it points to the Method Add (int x, int y) of the object test ). In C #, the delegate is always a constructor with a parameter in syntax. this parameter is the delegate pointing method. This method must match the signature of the initially defined delegate. In the preceding example, the delegate is defined as follows: "delegate string GetString ();" requires that the return type of the delegate function is string, if test. if the return value of Add (int x, int y) is int, the compiler reports an error. Pay attention to the value 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 Delegate constructor needs to transmit the address of the function, which is similar to the function pointer of C/C ++.

3. multicast Delegation

The number of calls to a delegate is the same as the number of calls to a method. To call multiple methods, you need to explicitly call the delegate multiple times. The delegate can also contain multiple methods. This type of delegation is called multicast delegation. If you call multicast delegates, you can call multiple methods in sequence. Therefore, the delegate signature must return void. Otherwise, only the result of the last method called by the delegate can be obtained.

For example:

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;

}

}

The "DoubleOp operation = MathOperation. multiplyByTwo; operation + = MathOperation. square; "is equivalent to" DoubleOp operation1 = MathOperation. multiplyByTwo; DoubleOp operation2 = MathOperation. square; DoubleOP operations = operation1 + operation2; ", multicast delegation can also recognize operators-and-=, used to delete method calls from the delegate.

Calling multiple methods through one multicast delegate poses another major problem. Multicast delegates include a set of calls to delegates one by one. If an exception is thrown by calling a method through a delegate, the entire iteration ends. In this case, you should manually iterate the method list to avoid this problem. You can use the Delegate class defined method 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 Two ()

{

Console. WriteLine ("Two ");

}

Static void Main ()

{

DemoDelegate dl = One;

Dl + = Two;

Try

{

Dl ();

}

Catch (Exception)

{

Console. WriteLine ("Exception caught! ");

}

}

}

Running 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 running result is as follows:

One

Exception caught

Two

Similarly, if the Delegate signature does not return the void, but you want to get all the results after the Delegate call, you can also use GetInvocationList () to get the Delegate object array, use the previous iteration method to obtain the returned results.

4. Anonymous Method

Another way to use delegation is to use the anonymous method. The anonymous method is a code block used as the 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 externally by the anonymous method and added to the parameters to be transferred. Then the code returns the string value. The advantage of the anonymous method is to reduce the code to be written. You do not need to define methods that are only used by delegation. This is obvious when you define a delegate for an event. This helps reduce the complexity of the Code, especially when several events are defined, the code is relatively simple. The code is not executed very quickly when the anonymous method is used.

When using the anonymous method, you must follow the following rules:

1) The jump statement cannot be used in the anonymous method to jump outside the anonymous method;

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

3) You cannot access Insecure code or the ref and out parameters used outside the anonymous method, but you can use other variables defined outside the anonymous method.

5. Lambda expressions

This is a new method provided by C #3.0 for anonymous methods. As shown in the preceding statement:

...

Static void Main ()

{

String mid = ...;

DelegateString anonDel = param =>

{

Param + = mid;

Param + = "and end ";

Return param;

};

...

}

...

Lambda expression => lists the parameters required by the anonymous method on the left and the implementation code on the right. The implementation code is placed in curly brackets, similar to the previous anonymous method. If there is only one line of implementation code, you can delete curly braces and return statements, which are automatically added by the compiler.

For example, public delegate bool Predicate (int val );

Predicate pl = x => x> 5;

In the preceding Lambda expression, variable x is defined on the left. The variable type is automatically set to int, because this is defined by delegation, and the code returns a boolean result of comparing x to 5. If x is greater than 5, true is returned; otherwise, false is returned.

6. Coordination and resistance to changes

The method called by the delegate does not need to be of the same type as the definition of the delegate declaration. As a result, there is a change in coordination and resistance.

1) return type covariant

The return type of a method can be derived from the type defined by the delegate. 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 above Code, the delegate MyDelegate is defined as the return DelegateReturn type. The method granted to the Delegate instance d1 returns the DelegateReturn2 type. DelegateReturn2 is derived from Delegate. Based on the relationship of the subclass "yes" parent class, the Delegate needs to be met. This is called the covariant of the return type.

2) Variable Resistance

The parameter defined by the delegate may be different from the method called by the delegate. The return type is different here, because the parameter type used by the method may be derived 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 above Code, the parameter type used by the delegate is DelegateParam2, while the parameter type used by the delegate instance d2 method is DelegateParam, and DelegateParam is the base class of delegateparam2.

Related Article

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.