委托的学习笔记

Posted on 2005-05-27 10:00  ppooqq的专栏  阅读(204)  评论(0)    收藏  举报
Part One
Notes:介绍委托的用途、定义、声明、实例、调用
 C#中的委托和指针不一样:
 指针不通过MSIL而是直接和内存打交道,这也是指针不安全的原因所在,当然也是采用指针能够提高程序运行速度的缘故;
 委托不与内存打交道,而是把这一工作交给CLR去完成。CLR无法阻止将不安全的代码调用到本机(非托管)代码中或执行恶意操作。然而当代码是类型安全时,CLR的安全性强制机制确保代码不会访问本机代码,除非它有访问本机代码的权限。

 委托派生于基类System.Delegate,不过委托的定义和常规类的定义方法不太一样。委托的定义通过关键字delegate来定义: 
public delegate int myDelegate(int x,int y); 
 上面的代码定义了一个新委托,它可以封装任何返回为int,带有两个int类型参数的方法。任何一个方法无论是实例方法还是静态方法,只要他们的‘签名’(参数类型在一个方法中的顺序)和定义的委托是一样的,都可以把他们封装到委托中去。这种签名方法正是保证委托是类型安全的手段之一。

 产生委托实例和产生类实例(对象)差不多,假如我们有如下的方法:

public int sub(int x,int y)

{

 return(x+y);

}

 我们就可以使用如下的代码得到一个委托实例:

myDelegate calculatin=new myDelegate(sub);

 接下来我们就可以直接使用calculation调用sub方法了:

calculation(10,3);

Part Two
Notes:委托的一个例子,用委托来实现《函数指针》里的例子

using System;

class MathClass
{
 public static int max(int a,int b)
 {
 return(a>b?a:b);
 }

 public static int min(int a,int b)
 {
 return(a }

 public static int sub(int a,int b)
 {
 return (a+b);
 }

 public static int minus(int a,int b)
 {
 return (a-b);
 }
}

class Handler
{
 private delegate int Calculation(int a, int b); //声明一个委托
 private static Calculation[] myCalculation=new Calculation[2];//委托的实例化,这里是一个委托数组

 public static void EventHandler(int i,int a,int b)
 {
 switch (i)
 {
 case 1:
 myCalculation[0]=new Calculation(MathClass.max);
 myCalculation[1]=new Calculation(MathClass.min);
 Console.WriteLine(myCalculation[0](a,b));
 Console.WriteLine(myCalculation[1](a,b));
 break;
 case 2:
 myCalculation[0]=new Calculation(MathClass.sub);
 myCalculation[1]=new Calculation(MathClass.minus);
 Console.WriteLine(myCalculation[0](a,b));
 Console.WriteLine(myCalculation[1](a,b));
 break;
 default:
 return;
 }
 }
}

class Test
{
 static void Main()
 {
 Handler.EventHandler(1,10,3);
 Handler.EventHandler(2,10,3);
 }
}

 我们还可以声明一个委托数组,就像声明一个对象数组一样,上面的例子中就使用到了委托数组;
 一个委托还可以封装多个方法(多路广播委托,经常与事件处理程序结合使用),只要这些方法的签名是正确的。多路广播委托的返回值一般为void,这是因为一个委托只能有一个返回值,如果一个返回值不为void的委托封装了多个方法时,只能得到最后封装的方法的返回值,这可能和用户初衷不一致,同时也会给管理带来不方便。如果你想通过委托返回多个值,最好是使用委托数组,让每个委托封装一个方法,各自返回一个值。

Part Three
Notes:介绍委托的一个重要应用——事件

事件

在C#中,委托的最基本的一个用处就是用于事件处理。事件是对象发送的消息,以发信号通知操作的发生,通俗一点讲,事件就是程序中产生了一件需要处理的信号。

事件的定义用关键字event声明,不过声明事件之前必须存在一个多路广播委托:

public delegate void Calculate(int x,int y);//返回值为void的委托自动成为多路广播委托;
public event calculate OnCalculate;
从上节的委托实例和上面的事件的声明可以看出,事件的声明仅仅是比委托实例的声明多了个关键字event,事实上事件可以看作是一个为事件处理过程定制的多路广播委托。因此,定义了事件后,我们就可以通过向事件中操作符+=添加方法实现事件的预定或者是通过-=取消一个事件,如:
this.Load += new System.EventHandler(this.Page_Load);
这些都与委托实例的处理是相同的。与委托实例不同的是,操作符=对于事件是无效的,即
OnCalculate=new calculate(sub) ;//无效
只是因为上面的语句会删除由OnCalculate封装的所有其他方法,指封装了由此语句指定的唯一方法,而且一个预定可以删除其他所有方法,这会导致混乱。

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3