1.委托的定义
官网解释:委托类型表示对具有特定参数列表和返回类型的方法的引用。 通过委托,可以将方法视为可分配给变量并可作为参数
传递的实体。委托还类似于其他一些语言中存在的“函数指针”概念。 与函数指针不同,委托是面向对象且类型安全的。
说明:
(1)可以直接定义在命名空间下面,与其他的类平级,也可以定义在类的内部,如果定义在类的内部则需要调用该类的成员才能使用。
(2)委托类似于方法(或函数)的模板,相当于是对方法的抽象,而类是对一组属性和行为的抽象。
1.1委托的声明
访问修饰符 delegate 返回值 方法名(形参列表)
public delegate double Test(double r)
1.2委托的实例化
委托的使用类似于普通的类,可以理解为特殊的类,使用new关键字创建委托对象。
委托 委托对象 = new 委托(方法名);
Program p = new Program();
Test t1 = new Test(ExamTest);
Test t2 = new Test(p.CommonTest);
上述代码中,委托对象t1就指向了ExamTest,t2对象就指向了CommonTest方法。
注意:此处的方法名所代表的方法必须与声明委托的方法签名一样,也就是说,ExamTest方法的返回值和参数列表与Test委托一致
//此处ExamTest为静态方法,可以在Program类的main方法中直接调用
public static double ExamTest(double score) { return 0.6 * score; }
//此处CommonTest为实例方法,需要在Program类的对象中调用 public double CommonTest(double score) { return 0.4 * score; }
2.委托类型的使用
再定义个方法,以委托类型Test的对象为形参
public string TotalTest(Test T1, Test T2) { return String.Format("期末总成绩为期考成绩*0.6={0}+平时成绩*0.4={1}的和={2}", T1(90.4), T2(86.3), T1(90.4) + T2(86.3)); }
需要注意的是,在具体使用委托对象时(也就是需要委托对象所代表的方法返回值)做计算,返回值等操作,委托对象T1,和T2就必须要有参数列表并给定实参,如T1(90.4), T2(86.3),且实参的类型需要与定义时的形参类型相同。
在main方法中调用
Program p = new Program();
//此处分别创建了2个委托对象,分别指向了静态方法ExamTest和实例方法CommonTest
Test t1 = new Test(ExamTest);
Test t2 = new Test(p.CommonTest);
Console.WriteLine(p.TotalTest(t1, t2));
运行结果
3.小结
(1)委托类型是方法的抽象,可以使用委托类型作为方法的形参,代表了一组返回值和形参列表相同的方法。类似接口可以作为方法的形参,实现这个接口的类都可以替换该接口作为方法的实参。接口实现了类级别的多态,委托实现了“方法”级别的多态,虽然不准确,但是可以这么理解。
(2)委托对象做为方法的形参时(如public string TotalTest(Test T1, Test T2)),如果需要用到委托类型的返回值时,必须加上所指向方法的实参(如commonTest(86.3), examTest(90.4))。委托对象作为形参时,不关心将来需要指向的方法是谁,只有当委托对象有具体指向的方法,并需要使用到方法的返回值时,才需要加上指定类型的实参。
4.源代码
using System; namespace 委托3 { class Program { public delegate double Test(double r); //此处ExamTest为静态方法,可以在Program类的main方法中直接调用 public static double ExamTest(double score) { return 0.6 * score; } //此处CommonTest为实例方法,需要在Program类的对象中调用 public double CommonTest(double score) { return 0.4 * score; } //委托对象t1,t2作为其他方法形参时,可以指向任何返回值与形参列表相同的方法 public string TotalTest(Test T1, Test T2) { return String.Format("期末总成绩为期考成绩*0.6={0}+平时成绩*0.4={1}的和={2}", T1(90.4), T2(86.3), T1(90.4) + T2(86.3));//委托对象(实参),相当于指定了实参,调用了一组返回值与形参列表相同的方法 } public string TotalTest(double[] score, Test T1, Test T2) { return String.Format("期末总成绩为期考成绩*0.6={0}+平时成绩*0.4={1}的和={2}", T1(score[0]), T2(score[1]), T1(score[0]) + T2(score[1])); } static void Main(string[] args) { Program p = new Program(); //此处分别创建了2个委托对象,分别指向了静态方法ExamTest和实例方法CommonTest Test t1 = new Test(ExamTest); Test t2 = new Test(p.CommonTest); /*TotalTest方法的形参是2个已经指向了具体方法的委托对象,具体方法的需要的实参已经在 TotalTest方法中指定了,如 T1(90.4), T2(86.3), T1(90.4) + T2(86.3)*/ Console.WriteLine(p.TotalTest(t1, t2)); //模仿官网的例子写了个TotalTest的重载函数,在另外一个形参中初始化2个委托对象所需要的实参 double[] score = { 90.4,86.3}; Console.WriteLine(p.TotalTest(score,t1, t2));
Console.ReadLine();
} } }
参考文章:
https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/delegates
https://blog.csdn.net/lizhenxiqnmlgb/article/details/82141968
T1