委托与事件

委托:譬如别人委托你买你去书挑选一本好的c#的书,而你却因为懒得动,直接去了dearbook选书,然后送上门。然后你转交给了朋友。这就是现实中的委托。-------你的好朋友并不知道,你没有去书店选。(不关注方法的细节)
c#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。委托代表了方法。
为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确

 2using System;
 3
 4namespace test1
 5{
 6 /// <summary>
 7 /// Class1 的摘要说明。
 8 /// </summary>

 9 
10 class MathsOperations
11 {
12  public static double multiplyByTwo(double value)
13  {
14   return value*2;
15  }

16
17  public static double Square(double value)
18  {
19   return value*value;
20  }

21 }

22
23 delegate double DoubleOp(double x);
24
25 class test1
26 {
27  static void Main()
28  {
29   DoubleOp[] operations =
30    {
31     new DoubleOp(MathsOperations.multiplyByTwo),
32     new DoubleOp(MathsOperations.Square)
33    }
;
34
35   for(int i=0;i<operations.Length;i++)
36   {
37    Console.WriteLine("Using operations[{0}];",i);
38    ProcessAndDisplayNumber(operations[i],2.0);
39    ProcessAndDisplayNumber(operations[i],5);
40    Console.WriteLine();
41   }

42  }

43
44  static void ProcessAndDisplayNumber(DoubleOp action,double value)
45  {
46   double result = action(value);
47   Console.WriteLine("Value is {0},result of operation is {1}",value,result);
48  }

49 }

50 
51
52}

有些时候不用委托是很难实现某些功能的
 1    class BubbleSorter
 2    {
 3        static public void Sort(object[] sortArray,CompareOp gtMethod)
 4        {
 5            for(int i=0;i<sortArray.Length;i++)
 6            {
 7                for(int j=i+i;i<sortArray.Length;j++)
 8                {
 9                    if(gtMethod(sortArray[j],sortArray[i]))
10                    {
11                        object temp = sortArray[i];
12                        sortArray[i] = sortArray[j];
13                        sortArray[j] = temp;
14                    }

15                }

16            }

17        }

18    }

19
20    delegate bool CompareOp(object lhs,object rhs);
21
22    class Employee
23    {
24        private string name;
25        private decimal salary;
26
27        public Employee(string name,decimal salary)
28        {
29            this.name=name;
30            this.salary=salary;
31        }

32        public override string ToString()
33        {
34            return string.Format(name + ",{0:c}",salary);
35        }

36        public static bool RhslsGreater(object lhs,object rhs)
37        {
38            Employee empLhs = (Employee)lhs;
39            Employee empRhs = (Employee)rhs;
40            return(empLhs.salary>empRhs.salary)?true:false;
41        }

42    }

43
44
45    class test1
46    {
47        static void Main()
48        {
49            Employee [] employees = 
50            {
51                new Employee("abc",100),
52                new Employee("bbc",122),
53                new Employee("bb",111),
54            }
;
55
56
57            CompareOp employeeCompareOp = new CompareOp(Employee.RhslsGreater);
58            BubbleSorter.Sort(employees,employeeCompareOp);
59
60            for(int i=0;i<employees.Length;i++)
61            {
62                Console.WriteLine(employees[i].ToString());
63            }

64        }

65    }

66}
多播委托:委托包含多个方法。按顺序连续调用多个方法,委托的签名必须返回void(否则,返回值应送到何处)。实际上,如果编译器发现某个委托返回void,就会自动假定这是一个多播委托
例子:
 1using System;
 2
 3namespace test1
 4{
 5    /// <summary>
 6    /// Class1 的摘要说明。
 7    ///</summary>

 8    
 9        class MathsOperations
10        {
11            public static void multiplyByTwo(double value)
12            {
13                double result = value*2;
14                Console.WriteLine(
15                    "Multiplying by 2:{0} gives {1}",value,result);
16            }

17    
18            public static void Square(double value)
19            {
20                double result = value*value;
21                Console.WriteLine(
22                    "Squareing:{0} gives {1}",value,result);
23            }
    
24        }

25    
26        delegate void DoubleOp(double value);
27    
28        class test1
29        {
30            static void Main()
31            {
32                 //或,委托可以识别 +,+=,-,-=
33                //DoubleOp operations = new DoubleOp(MathsOperations.multiplyByTwo);
34                //operations += new DoubleOp(MathsOperations.Square);
35
36                DoubleOp opertaion1 = new DoubleOp(MathsOperations.multiplyByTwo);
37                DoubleOp operation2 = new DoubleOp(MathsOperations.Square);
38                DoubleOp operations = opertaion1 + operation2;
39
40                ProcessAndDisplayNumber(operations,2.0);
41                ProcessAndDisplayNumber(operations,40.0);
42            }

43    
44            static void ProcessAndDisplayNumber(DoubleOp action,double value)
45            {
46                Console.WriteLine("\nProcessAndDisplay Number called with value = " +
47                    value);
48                action(value);
49            }

50        }

51}

事件:事件与委托是密不可分的。
应用程序是通过windows来通信的,而windows又是使用预定义的消息与应用程序通信的。微软已经定义好了N多个系统事件(消息),譬如点击一个摁钮,打开一个下拉框,等等。事件接收器就是指发生某事件时被通知的任何应用程序,对象或组件。事件发送器可以是应用程序的一个对象或程序集。系统事件中如鼠标单击,键盘按键。.net程序中的事件发送器就是.net的运行库,.net framework把windows消息封装在了事件中,偶没学过windows编程,对windows消息的机制不甚了解。大概就是button的click事件封装了windows的WM_MOUSECLICK消息。然后就可以直接调用click事件了。
button1.click  += new EventHandler(Button_Click);
事件              +=    实例化一个委托(某个方法)   //可多个方法依次添加到委托列表,但不能保证调用时方法的顺序。
EventHandler 委托在Farmework是已定义的,位于System命名空间,在所有的Farmework中的定义的事件都是用它。添加到该委托列表的方法都必须有相同的签名。private void Button_Click(object sender , Eventargs e) //1参:引发事件的对象,2参:包含有关事件的其他有用信息的对象,可任意类型,只要派生于它均可,譬如MouseDownEventArgs 类型。

委托和事件在用户界面程序里用的比较的多,比如象在winformwebform的用户UI上的button和它的click事件:

// Button1_Click()方法绑定到按钮控件Button1Click事件上

this.Button1.Click += new System.EventHandler(this. Button1_Click);

 

private void Button1_Click(object sender, System.EventArgs e)    // Button1_Click()方法

{

                …… 

}

 

然而除了用户界面程序外,在很多其他地方也用到了事件驱动模式,比如观察者模式(Observer)或发布/订阅(Publish/Subscribe)里:在一个类里发布(Publish)某个可以被触发的事件,而其他的类就可以来订阅(Subscribe)该事件。一旦这个发布者类触发了该事件,那么运行时环境会立刻告知所有订阅了该事件的订阅者类:这个事件发生了!从而各个订阅者类可以作出它们自己的反应(调用相应方法)。

 


posted @ 2007-01-31 00:51  微微一记  阅读(610)  评论(0编辑  收藏  举报