加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

(C#)委托

(2011-11-17 15:49:48)
标签:

委托

csharp

分类: C#笔记

委托

 

委托的基本概念

把一个方法(函数)作为另一个方法(函数)的参数

“委托”

“委托”与C#的事件机制

 

(本文中的代码均在VS2005中运行过。启动VS2005,新建一个C#语言控制台应用程序项目,将本文中代码复盖原自动生成的代码,启动调试,就可以看到运行结果)

 

一)委托的基本概念

面向对象编程的基本思想之一,就是将具有共同特征的某一类具体对象抽象为类。考察下面两个函数(方法):

void multiply (int m, int n){ return m*n; }

void divide   (int x, int y){ return x/y; }

这两个函数(方法)有一个共同特征:具有相同的Parament List and Return Value(又可称为具有相同的签名)。在C#中,可以把这种具有相同签名的函数(方法)抽象为一种“类”-----这种“类”,在C#中被称作“委托(delegate)”。

声明“委托”的关键字是“delegate”。对于上面的两个方法,我们可以用如下语句声明一个名为MyDelegate的“委托”:

public delegate void MyDelegate(int a, int b);

创建“委托”实例的语法与创建其它类的实例一样,下面语句就创建了一个名为dg1的实例,可以用它来替代multiply函数:

MyDelegate dg1 = new MyDelegate(multiply);// “委托”类有一个参数为函数名的构造函数

特别的是,“委托”还可以象一般变量一样,用一个方法名对它进行赋值。下面的代码与上面的代码等效:

      MyDelegate dg1 = multiply

这一句也可读作:委托dg1来代理执行multiply函数。如果把dg1比作C C++ 中的“函数指针”,这一句就是将dg1指向multiply函数的入口地址。(实际上,C#的“委托”就是用来替代C C++ 中的“函数指针”的)。

下面一段完整的代码演示了“委托” 最基本、最简单的用法:

 

using System;

namespace DelegateSample//namespace:命名空间(类似于JAVA中的“包”)

{

   //声明一个委托(Return Valueint Parament List(int a, int b)

    public  delegate int myDelegate(int a, int b);

   

    class DelegateSample1

    {

         public static int multiply (int m, int n) //静态方法

            { return m*n; }

         public static int divide(int x, int y)

           { return x/y; }

 

        public static void Main(string[] args)

        {

            //以下用两种不同的方式创建委托的实例

 myDelegate dg1,dg2;

dg1 = new myDelegate(multiply);

            dg2 = divide;

              

            Console.WriteLine(dg1(50,10));

            Console.WriteLine(dg2(100,20));

            Console.ReadLine();

        }

    }

}

 

运行结果,屏幕显示:

500

5

 

二)把一个方法(函数)作为另一个方法(函数)的参数

把一个方法(函数)作为另一个方法(函数)的参数,在较为复杂的程序设计中非常有用。-----因为它可以将类中的方法(函数)与具体的操作(方法的执行体)分离,这样,当具体的操作发生更改时,只需重新绑定该方法即可,而不用重写类。 CC++语言是通过“函数指针”实现这一功能的,而C#则通过“委托”。

下面示例中的Add函数,就是将一个“委托”作为参数,任何一个与这个“委托”有相同签名的函数,都可以作为实参传递给它。

 

using System;

namespace DelegateSample

{

   //声明一个委托(Return ValueintParament List(int a, int b)

    public  delegate int myDelegate(int a, int b);

        class DelegateSample1

    {

         public static int multiply (int m, int n) //静态方法

            { return m*n; }

         public static int divide(int x, int y)

           { return x/y; }

       //

        public static int Add(int x1, int x2,int y1,int y2, myDelegate myCalcu)

           {

               return myCalcu(x1,x2) + myCalcu(y1,y2);

           }

 

        public static void Main(string[] args)

        {

             Console.WriteLine( Add(50,50,10,10,multiply) );  //计算 50*50 + 10*10

            Console.WriteLine( Add(50,50,10,10,divide) );   //计算 50/50 + 10/10

            Console.ReadLine();

        }

    }

}

 

运行结果,屏幕显示:

2600

 2

 

三)“委托”链

“委托”可以用“+”运算符来组合,从而形成一个委托链。当然,只有具有相同签名的委托才可以组合。-运算符可用来从委托链移除委托。

 

using System;

namespace DelegateSample

{

   public  delegate void myDelegate();

   

    class DelegateSample2

   

        public static void Function1() //静态方法

        { Console.WriteLine("this is Function1"); }

        public static void Function2()

        { Console.WriteLine("this is Function2"); }

        public static void Function3()

        { Console.WriteLine("this is Function3"); }

      

        public static void Main(string[] args)

        {

            myDelegate dg, dg1, dg2,dg3;

          dg1 = Function1;

          dg2 = Function2;

          dg3 = Function3;

          dg  = dg1 + dg2; //dg1da2组合成一个链dg

          dg  += dg3;      // dg1dg2da3组合成一个链dg

          dg();         

          Console.ReadLine();

          dg -= dg1; //移除dg1

          dg();

          Console.ReadKey();

        }

    }

}

 

 

运行结果,屏幕显示:

this is Function1

this is Function2

this is Function3

 

按回车键后,屏幕显示:

 this is Function2

this is Function3

 

前面说过,“委托”类似于C语言中的函数指针。如果说一个函数指针存放一个函数的入口地址,则一个“委托”可以存放多个函数的入口地址(当然这些函数必须有相同的返回值和参数)。

“委托”的这个特点,是构建C#的事件机制基础之一。

四)“委托”与C#的事件机制

C#的事件机制,可以简单描述如下:

假设A对象有一个e事件,当e事件发生时,B1B2B3……等众多对象都会执行各自的e事件响应函数。-----这一过程,用C#语言是这样来实现:

A对象中设置一个委托链,B1B2B3……等对象可以将各自的事件响应函数用“+=”运算符加入到这个委托链中(此操作又称注册)。这样,当A对象的e事件发生时,就可以通过这个委托链来回调B1B2B3……等对象的e事件响应函数。

为了安全起见,C#将上述的A对象的委托链进一步包装为event , 经过包装的event,实质上是加了保护层的delegate, 它仅允许其它对象对它进行“+=”或“-=”操作,以保证A对象的“封装性”不受影响)。

详见《事件event

 

0

阅读 收藏 喜欢 打印举报/Report
前一篇:(C#)五子棋
后一篇:(C#)事件
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有