一.在C#中我们可以使用delegate关键字来声明一个委托,声明的格式如下: delegate <函数返回类型> <委托名> (<函数参数>) 下面我们来看一下代码是如何来写的: [C] 纯文本查看 复制代码 using System;using System.Collections.Generic;namespace demo{ //声明一个委托,两个int类型的参数,一个int类型的返回值 delegate int MyDelegate(int x,int y); class Test { //求两个数的和,两个int类型的参数,int类型的返回值; public int Sum(int a, int b) { return a + b; } //两个数的差,两个int类型的参数,int类型的返回值 static public int Min(int a, int b) { return a - b; } } class MainClass { public static void Main(string[] args) { //创建Test类的一个对象 Test test = new Test(); //声明一个MyDelegate类型的变量,由于该类型的委托在声明时有两个int类型的参数和int类型的返回值 //其格式与Test类中Sum和Min两个方法的格式一样,故可以直接把这两个方法赋值给该委托类型的变量mydel //这时可以说委托绑定了方法,它不仅可以绑定类方法,也可以绑定实例方法 MyDelegate mydel = Test.Min;//绑定了类方法 MyDelegate mydel1 = test.Sum;//绑定了实例方法 //委托变量的使用与方法的使用是一样的,也要带参数,也有返回值 Console.WriteLine(mydel1(2, 3)); } }} 在名字空间内部,类的外部创建一个委托类型MyDelegate,其声明的格式为:返回值int类型,参数有两个,都是int类型.大家可以看到该委托的格式与Test类里面的Sum和Min方法在格式外形上来看是一致的.在Main方法里面,我们就可以把Sum方法直接赋值给MyDelegate的一个变量,此时我们可以说把一个方法绑定给了一个委托变量,从上面的代码中可以看到,委托不仅可以绑定类方法,也可以绑定实例方法. 从上面的代码我们可以得到如下的结论: 1.在声明委托时有一定的格式,我们就可以把与该委托格式一样的方法名直接赋值给该委托的一个变量; 2.从某种意义上来讲,委托相当于一个方法模版,把与该模版相同的方法赋值给委托变量后,使用委托变量时,本质上来讲就是使用其所绑定的方法; 3.委托变量的使用与方法的使用是一样的,如果有参数,委托变量后面一定要带小括号,里面要加参数,并且个数和类型要一致,如果没有参数,也要加小括号; (其它三种格式的委托大家可以自己练习试着做一下) 委托不仅可以绑定一个方法,还可以绑定多个方法,如下代码: [C] 纯文本查看 复制代码 using System;using System.Collections.Generic;namespace demo{ //声明一个委托,一个string类型的参数,无返回值 delegate void GreetDelegate(string str); class Test { //一个string类型的参数,无返回值 public void ChineseGreet(string name) { Console.WriteLine("早上好!!" + name); } //一个string类型的参数,无返回值 public void EnglishGreet(string name) { Console.WriteLine("Good morning!!" + name); } } class MainClass { public static void Main(string[] args) { //创建Test类的一个对象 Test test = new Test(); //绑定了第一个方法 GreetDelegate greet = test.ChineseGreet; //绑定第二个方法,用+=运算符,通常称为委托合并 greet += test.EnglishGreet; greet("lisi"); } }} 我们在给委托变量绑定第一个方法时,直接用赋值运算符,这样才可以使委托变量进行实例化,否则是不能用的,绑定第二个方法时,用+=运算符,这样委托变量就同时绑定了两个方法,通常也称为委托合并,在Main方法里面使用委托时,会调用所绑定的两个方法,把结果打印出来,所绑定的方法是有先后顺序的,先绑定的方法会先执行.使用委托时只需要记住一点:即委托所绑定的方法从格式上二者要一致. 以上的两个例子,委托在绑定方法时,都会先把方法创建好,下面讲另外两种委托,匿名委托和lambda表达,这样就不用再创建方法了.下面的代码是把上面的例子用匿名委托改写的,代码如下: [C] 纯文本查看 复制代码 public static void Main(string[] args) { Greet greet = delegate(string str) { Console.WriteLine("早上好!!" + str); }; greet += delegate(string str) { Console.WriteLine("Good Morning!!" + str); }; greet("小李"); } 其结果与上面的一样,使用匿名委托时其格式为:delegate(){};小括号里面为参数,大括号里面是方法体,具体是否有返回值,以及参数个数和参数类型要与其所赋值的委托格式一致,如果有返回值,则只需要在大括号里面return一个返回值即可;如把上面的第一个例子用匿名委托更改如下: [C] 纯文本查看 复制代码 MyDelegate mydele = delegate(int a, int b) { return a + b; }; 由于MyDelegate的格式为:返回值为int类型,参数2个,都是int类型,所以匿名委托的参数也要有两个并且都是int类型,在{}里面要有一个返回值.下面再看另外一种匿名委托,lambda表达式,其在C++中称为闭包,其格式如下: (()=>{}),具体的使用方法请看以下代码: [C] 纯文本查看 复制代码 MyDelegate mydele = ((int a, int b) => { return a + b; }); Console.WriteLine(mydele(2, 3)); 结果和上面的例子是一样的.大家只需要记住其格式即可,(()=>{}),小括号里时面是参数,大括号里面是方法体.只要大家看得多了,就会习惯这种编程方法了. 下面一种委托是Func委托,格式为Func<形参1类型,形参2类型...返回值类型> 委托变量名;<>里面的最后一个为返回值类型,前面的都是参数类型,该委托一定要有返回值.具体的代码如下: [C] 纯文本查看 复制代码 Func 最后一种委托是Action委托,格式为Action<形参类型> 委托变量名;<>里面是形参类型,参数可以有多个,此委托没有返回值,具体的用法如下代码: [C] 纯文本查看 复制代码 Action 二.上面的例子我们看到,定义的委托都是在类外面,名字空间下面的,所有的类都可以用该委托,这与我们讲的面向对象的三大特性封装是相违背的,此时我们就把委托放到类里面,然后在类里面创建一个public修饰的委托变量,然后在类的外面就可以拿到该委托变量,进而使用它.具体的代码如下: [C] 纯文本查看 复制代码 class Test { public delegate void PrintDelegate(); public PrintDelegate printdel;public void Print() { Console.WriteLine("蓝鸥科技"); }}//下面是Main方法public static void Main(string[] args) { //创建Test类的一个对象 Test test = new Test(); test.printdel = test.Print; test.printdel();} 具体的其它用法同上面; 三.event关键字如果类里面的一个委托变量用public event来修饰,在类的外面可以直接拿到该委托变量,并且在绑定方法的时候,只能用+=运算符,即使绑定第一个方法,也要用+=运算符,但是有一点,绑定方法以后,不能够直接使用,必须把该委托变量放到类里面的方法里面.具体的代码如下:[C] 纯文本查看 复制代码 class Test { public delegate void PrintDelegate(); public PrintDelegate printdel; //用event修饰委托变量 public event PrintDelegate eventdelegate;//调用该方法,才可以执行方法里面的委托 public void EventPrint(){ eventdelegate(); } public void Print() { Console.WriteLine("蓝鸥科技"); }} public static void Main(string[] args) { //创建Test类的一个对象 Test test = new Test();test.eventdelegate += test.Print; test.EventPrint();}event修饰的委托也可以绑定多个方法,用法同上; |