C#委托初探

委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。您可以通过委托调用其中已添加的方法列表。委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法。button的单击事件发生后,通过委托这个管道找到用户添加的处理方法,从而执行方法;不必像之前win32程序那样循环等待某个事件消息。

先直接添端代码进来,

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace Test_Delegate
 7 {
 8     //定义一个委托,对应方法签名为 int Fun(int , int )
 9     //编译器会自动生成一个委托类 dgOP,在此相当于声明一个类对象,稍后使用时new实例化
10     //继承链如:Delegate:MulticastDelegate:Delegate:ICloneable,ISerializable
11     public delegate int dgOP(int x, int y);
12     //生成的类形如
13     //sealed class dgOP : System.MulticastDelegate
14     //{
15     //    //构造函数,原理不清楚  !!
16     //    public dgOP(object target,unit functionAddr);
17     //    //成员函数,可在外调用
18     //    public virtual int Invoke(int x, int y);  
19     //    public virtual IAsyncResult BeginInvoke(int x, int y
20     //        , AsyncCallback callback, object @object);
21     //    public virtual int EndInvoke(IAsyncResult result);
22     //}
23     
24     public class SimpleMath
25     {
26         /***********静态方法*******************/
27         public static int Add(int x, int y)
28         {
29             Console.WriteLine("add");
30             return x + y;
31         }
32         public static int Square(int x)
33         {
34             return x * x;
35         }
36         /***********动态方法*******************/
37        
38         public int Sub(int x, int y)
39         {
40             Console.WriteLine("sub");
41             return x - y;
42         }
43     }
44 
45     class Program
46     {
47         static dgOP dg;
48         static void Main(string[] args)
49         {
50             //静态方法
51             //实例化上文中定义的(编译器自动生成的)委托类,并指定方法
52             //+=内部隐式调用dgOP.Combine
53             //Del(new dgOP(SimpleMath.Add));
54             dg = dgOP.Combine(new dgOP(SimpleMath.Add),new dgOP(new SimpleMath().Sub)) as dgOP;
55             //执行调用列表的函数,但最终只返回最后一个函数调用返回值。
56             //dg(10 , 20)内部隐式调用 dg.Invoke(20 , 10)
57             Tools.OutputParams(dg(10 , 20));
58             Tools.OutputParams(dg.Invoke(20, 10));
59             //DisplayDelegate(dg);
60             Tools.NewLine();
61 
62             ////动态方法
63             //SimpleMath m=new SimpleMath();
64             //dgOP dg2 = new dgOP(m.Sub);
65             //Tools.OutputParams(dg2(10,20),dg2.Invoke(20,10));
66             //DisplayDelegate(dg2);
67             ////委托已经声明为方法签名为:void Fun(int x,int y),对应2个参数
68             ////SimpleMath.Square只含一个参数
69             ////dgOP dg3 = new dgOP(SimpleMath.Square);
70 
71             Tools.Pause();
72         }
73 
74         private static void Del(dgOP dgOP)
75         {
76             dg += dgOP;
77         }
78 
79     
80 
81         private static dgOP Del()
82         {
83             dgOP dg = new dgOP(SimpleMath.Add);
84             dg += new dgOP(new SimpleMath().Sub);
85             return dg;
86         }
87 
88         private static void DisplayDelegate(dgOP dg)
89         {
90             //输出委托列表内部的方法签名,类对象
91             foreach (Delegate item in dg.GetInvocationList())
92             {
93                 Tools.OutputParams(item.Method, item.Target);
94             }
95         }
96 
97 
98     }
99 }

Tools类只是个工具,用来输出值至控制台,或者另起一行,停止控制台。

 

委托是最底层,事件是较上层,用来简化处理委托声明,封装维护调用列表。

  1 #region Using directives
  2 
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Text;
  6 
  7 #endregion
  8 
  9 namespace CarEvents
 10 {
 11     class Program
 12     {
 13         static void Main(string[] args)
 14         {
 15             Console.WriteLine("***** Fun with Events *****\n");
 16 
 17             // Make a car as usual. 
 18             Car c1 = new Car("SlugBug", 100, 10);
 19 
 20             // Register event handlers.
 21             c1.AboutToBlow += new Car.CarEventHandler(c1_AboutToBlow);
 22             c1.AboutToBlow += new Car.CarEventHandler(CarIsAlmostDoomed);
 23             c1.AboutToBlow += new Car.CarEventHandler(CarAboutToBlow);
 24 
 25             Car.CarEventHandler d = new Car.CarEventHandler(CarExploded);
 26             c1.Exploded += d;
 27 
 28             // Speed up (this will generate the events.)
 29             Console.WriteLine("***** Speeding up *****");
 30             for (int i = 0; i < 6; i++)
 31                 c1.Accelerate(20);
 32 
 33             // Remove CarExploded method 
 34             // from invocation list.
 35             c1.Exploded -= d;
 36 
 37             Console.WriteLine("\n***** Speeding up *****");
 38             for (int i = 0; i < 6; i++)
 39                 c1.Accelerate(20);
 40 
 41             Console.ReadLine();
 42         }
 43 
 44         static void c1_AboutToBlow(string msg)
 45         {
 46             Console.WriteLine("xxxx");
 47         }
 48 
 49         public static void CarAboutToBlow(string msg)
 50         { Console.WriteLine(msg); }
 51 
 52         public static void CarIsAlmostDoomed(string msg)
 53         { Console.WriteLine("Critical Message from Car: {0}", msg); }
 54 
 55         public static void CarExploded(string msg)
 56         { Console.WriteLine(msg); }
 57 
 58     }
 59 }
 60 
 61 #region Using directives
 62 
 63 using System;
 64 using System.Collections.Generic;
 65 using System.Text;
 66 
 67 #endregion
 68 
 69 namespace CarEvents
 70 {
 71     public class Car
 72     {
 73         //// This delegate works in conjunction with the
 74         //// Car’s events.
 75         //public delegate void CarEventHandler(string msg);
 76 
 77         //// This car can send these events.
 78         //public event CarEventHandler Exploded;
 79         //public event CarEventHandler AboutToBlow;
 80 
 81         public delegate void CarEventHandler(string msg);
 82 
 83         public event CarEventHandler Exploded;
 84         public event CarEventHandler AboutToBlow;
 85         #region Basic Car members...
 86 
 87         #region Nested radio
 88         // Radio as nested type
 89         public class Radio
 90         {
 91             public void TurnOn(bool on)
 92             {
 93                 if (on)
 94                     Console.WriteLine("Jamming...");
 95                 else
 96                     Console.WriteLine("Quiet time...");
 97             }
 98         }
 99         #endregion
100 
101         // Internal state data.
102         private int currSpeed;
103         private int maxSpeed;
104         private string petName;
105 
106         // Is the car alive or dead?
107         bool carIsDead;
108 
109         // A car has-a radio.
110         private Radio theMusicBox = new Radio();
111 
112         public Car()
113         {
114             maxSpeed = 100;
115         }
116 
117         public Car(string name, int max, int curr)
118         {
119             currSpeed = curr;
120             maxSpeed = max;
121             petName = name;
122         }
123 
124         public void CrankTunes(bool state)
125         {
126             theMusicBox.TurnOn(state);
127         }
128         #endregion
129 
130         #region Accelerate method
131         public void Accelerate(int delta)
132         {
133             // If the car is dead, fire Exploded event.
134             if (carIsDead)
135             {
136                 if (Exploded != null)
137                     Exploded("Sorry, this car is dead...");
138             }
139             else
140             {
141                 currSpeed += delta;
142 
143                 // Almost dead?
144                 if (10 == maxSpeed - currSpeed
145                   && AboutToBlow != null)
146                 {
147                     AboutToBlow("Careful buddy!  Gonna blow!");
148                 }
149 
150                 // Still OK!
151                 if (currSpeed >= maxSpeed)
152                     carIsDead = true;
153                 else
154                     Console.WriteLine("->CurrSpeed = {0}", currSpeed);
155             }
156         }
157         #endregion
158 
159     }
160 }
View Code

匿名方法是简化了委托及方法定义,不必再手动定义方法,直接间写在委托中。

  1 #region Using directives
  2 
  3 using System;
  4 using System.Collections.Generic;
  5 using System.Text;
  6 
  7 #endregion
  8 
  9 namespace AnonymousMethods
 10 {
 11     class Program
 12     {
 13         static void Main(string[] args)
 14         {
 15             Console.WriteLine("***** Anonymous Methods *****");
 16 
 17             int aboutToBlowCounter = 0;
 18 
 19             // Make a car as usual. 
 20             Car c1 = new Car("SlugBug", 100, 10);
 21 
 22             // Register event handlers as anonymous methods.          
 23             c1.AboutToBlow += delegate
 24             {
 25                 aboutToBlowCounter++;
 26                 Console.WriteLine("Eek!  Going too fast!");
 27             };
 28 
 29             c1.AboutToBlow += delegate(object sender, CarEventArgs e)
 30             {
 31                 aboutToBlowCounter++;
 32                 Console.WriteLine("Message from Car: {0}", e.msg);
 33             };
 34 
 35             c1.Exploded += delegate(object sender, CarEventArgs e)
 36             { Console.WriteLine("Message from Car: {0}", e.msg); };
 37 
 38             // Speed up (this will generate the events.)
 39             Console.WriteLine("\n***** Speeding up *****");
 40             for (int i = 0; i < 6; i++)
 41                 c1.SpeedUp(20);
 42 
 43             Console.WriteLine("AboutToBlow event was fired {0} times",
 44               aboutToBlowCounter);
 45 
 46             Console.ReadLine();
 47         }
 48     }
 49 }
 50 #region Using directives
 51 
 52 using System;
 53 using System.Collections.Generic;
 54 using System.Text;
 55 
 56 #endregion
 57 
 58 namespace AnonymousMethods
 59 {
 60    //与上面的事件代码类似     
 61     public class CarEventArgs : EventArgs
 62     {
 63         public readonly string msg;
 64         public CarEventArgs(string message)
 65         {
 66             msg = message;
 67         }
 68     }
 69 
 70     public class Car
 71     {
 72         // This delegate works in conjunction with the
 73         // Car’s events.
 74         public delegate void CarEventHandler(object sender, CarEventArgs e);
 75 
 76         // This car can send these events.
 77         public event CarEventHandler Exploded;
 78         public event CarEventHandler AboutToBlow;
 79 
 80         #region Basic Car members...
 81         #region Nested radio
 82         // Radio as nested type
 83         public class Radio
 84         {
 85             public void TurnOn(bool on)
 86             {
 87                 if (on)
 88                     Console.WriteLine("Jamming...");
 89                 else
 90                     Console.WriteLine("Quiet time...");
 91             }
 92         }
 93         #endregion
 94 
 95         // Internal state data.
 96         private int currSpeed;
 97         private int maxSpeed;
 98         private string petName;
 99 
100         // Is the car alive or dead?
101         bool carIsDead;
102 
103         // A car has-a radio.
104         private Radio theMusicBox = new Radio();
105 
106         public Car()
107         {
108             maxSpeed = 100;
109         }
110 
111         public Car(string name, int max, int curr)
112         {
113             currSpeed = curr;
114             maxSpeed = max;
115             petName = name;
116         }
117 
118         public void CrankTunes(bool state)
119         {
120             theMusicBox.TurnOn(state);
121         }
122 #endregion 
123 
124         public void SpeedUp(int delta)
125         {
126             // If the car is dead, fire Exploded event.
127             if (carIsDead && Exploded != null)
128             {
129                 Exploded(this, new CarEventArgs("Sorry, this car is dead..."));
130             }
131             else
132             {
133                 currSpeed += delta;
134 
135                 // Almost dead?
136                 if (10 == maxSpeed - currSpeed
137                     && AboutToBlow != null)
138                 {
139                     AboutToBlow(this, new CarEventArgs("Careful buddy!  Gonna blow!"));
140                 }
141 
142                 // Still OK!
143                 if (currSpeed >= maxSpeed)
144                     carIsDead = true;
145                 else
146                     Console.WriteLine("->CurrSpeed = {0}", currSpeed);
147             }
148         }
149     }
150 }
View Code

而lambdar表达式则是对匿名方法的再次简化,由此可以引申出linq,ef的语法。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace SimpleLambdaExpressions
 7 {
 8   class Program
 9   {
10     static void Main(string[] args)
11     {
12       Console.WriteLine("***** Fun with Lambdas *****\n");
13       TraditionalDelegateSyntax();
14       AnonymousMethodSyntax();
15       
16       Console.WriteLine();
17       LambdaExpressionSyntax();
18 
19       Console.ReadLine();
20     }
21 
22     #region Traditional delegate syntax
23     static void TraditionalDelegateSyntax()
24     {
25       // Make a list of integers.
26       List<int> list = new List<int>();
27       list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });
28 
29       // Call FindAll() using traditional delegate syntax.
30       Predicate<int> callback = new Predicate<int>(IsEvenNumber);
31       List<int> evenNumbers = list.FindAll(callback);
32 
33       Console.WriteLine("Here are your even numbers:");
34       foreach (int evenNumber in evenNumbers)
35       {
36         Console.Write("{0}\t", evenNumber);
37       }
38       Console.WriteLine();
39     }
40     // Target for the Predicate<> delegate.
41     static bool IsEvenNumber(int i)
42     {
43       // Is it an even number?
44       return (i % 2) == 0;
45     }
46     #endregion 
47 
48     #region Anonymous method syntax
49     static void AnonymousMethodSyntax()
50     {
51       // Make a list of integers using C# 3.0
52       // collection initialization syntax. 
53       List<int> list = new List<int>();
54       list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });
55 
56       List<int> evenNumbers = list.FindAll(
57         delegate(int i)
58         {
59           return (i % 2) == 0;
60         }
61       );
62 
63       Console.WriteLine("Here are your even numbers:");
64       foreach (int evenNumber in evenNumbers)
65       {
66         Console.Write("{0}\t", evenNumber);
67       }
68       Console.WriteLine();
69     }
70     #endregion
71 
72     #region Lambda expression syntax
73     static void LambdaExpressionSyntax()
74     {
75       // Make a list of integers. 
76       List<int> list = new List<int>();   
77       list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });
78 
79       // Now process each argument within a group of 
80       // code statements.
81       List<int> evenNumbers = list.FindAll((i) => 
82       { 
83         Console.WriteLine("value of i is currently: {0}", i);
84         bool isEven = ((i % 2) == 0);
85         return isEven;
86       });
87 
88       Console.WriteLine("Here are your even numbers:");
89       foreach (int evenNumber in evenNumbers)
90       {
91         Console.Write("{0}\t", evenNumber);
92       }
93       Console.WriteLine();
94     }
95     #endregion
96   }
97 }
View Code

 

总结性的比较少,代码比较多。因为我还没有完全领悟,只是初步了解了下。

具体大家可以发挥google的优势。

 

posted on 2014-01-02 09:29  nlh774  阅读(2448)  评论(0编辑  收藏  举报