【个人学习】: C#委托
一、什么是委托
- 说到委托,将方法作为方法的参数进行传递,这是很多人对委托的第一印象,具体怎么个传递法,我们一起来看看。
二、实例学习委托
举个不是很恰当的例子:某个检测系统,检测到某国有某个工厂出现故障,需要及时通知工厂进行故障检修,第n天,故障修复,反响不错,各个工厂争先恐后的想要附加这个功能,针对这个不恰当的案例我们写一个案例:
- 不使用委托的情况下,我们这样写:
public static class DelegateService { /// <summary> /// 根据编码获取水厂名称 /// </summary> /// <param name="name"></param> /// <returns></returns> public static string GetCompanyByName(string name) { string fullName = string.Empty; switch (name) { case "slyt": fullName = GetSlytNameByShortName(name); break; case "zyyt": fullName = GetZyytNameByShortName(name); break; default: break; } return fullName; } /// <summary> /// 根据简称获取企业名称(胜利油田) /// </summary> private static string GetSlytNameByShortName(string shortName) { return "胜利油田"; } /// <summary> /// 根据简称获取企业名称(中原油田) /// </summary> private static string GetZyytNameByShortName(string shortName) { return "中原油田"; } }
string name = "slyt"; string fullName = DelegateService.GetCompanyByName(name); Console.WriteLine($"不使用委托:{fullName} 故障了,请检修");
- 以上共两家工厂,之后陆陆续续的工厂要求增加该功能,看了上面的代码,想了想。。恩。。我不想一直case,(这个解决方案可扩展性太次,加一加工厂,就得修改原有方法)
-
在想新解决方案之前,我们先看一下之前的方法 public static string GetCompanyByName(string name) 我们看 string name,在这里,string 是参数类型,name 是参数变量,当我们赋给name字符串“slyt”时,它就代表“slyt”这个值;当我们赋给它“zyyt”时,它又代表着“zyyt”这个值。然后,我们可以在方法体内对这个name进行其他操作。哎,这简直是废话么,刚学程序就知道了。
如果你再仔细想想,假如GetCompanyByName()方法可以接受一个参数变量,这个变量可以代表另一个方法,当我们给这个变量赋值 GetSlytNameByShortName的时候,它代表着 GetSlytNameByShortName() 这个方法;当我们给它赋值GetZyytNameByShortName的时候,它又代表着GetSlytNameByShortName()方法。我们将这个参数变量命名为 companyDelegate,那么不是可以如同给name赋值时一样,在调用 GetCompanyByName()方法的时候,给这个companyDelegate参数也赋上值么(GetSlytNameByShortName或者GetZyytNameByShortName等)?然后,我们在方法体内,也可以像使用别的参数一样使用companyDelegate。但是,由于companyDelegate代表着一个方法,它的使用方式应该和它被赋的方法(比如GetZyytNameByShortName)是一样的,比如:
public static string[] GetName(string name, *** companyDelegate)
{
string[] fullName = companyDelegate(name);
return fullName;
}
- 注意到 *** ,这个位置通常放置的应该是参数的类型,但到目前为止,我们仅仅是想到应该有个可以代表方法的参数,并按这个思路去改写GetName方法,现在就出现了一个大问题:这个代表着方法的companyDelegate参数应该是什么类型的?
聪明的你应该已经想到了,现在是委托该出场的时候了,但讲述委托之前,我们再看看companyDelegate参数所能代表的 GetSlytNameByShortName()和GetZyytNameByShortName()方法的签名:
public static string[] GetSlytNameByShortName(string shortName) public static string[] GetZyytNameByShortName(string shortName)
本例中委托的定义:
//定义委托 public delegate string[] CompanyDelegate(string name);
可以与上面GetSlytNameByShortName()方法的签名对比一下,除了加入了delegate关键字以外,其余的是不是完全一样?
现在,让我们再次改动GetName()方法,如下所示:
public static string[] GetName(string name, CompanyDelegate companyDelegate) { string[] fullName = companyDelegate(name); return fullName; }
下面我们看一下完成的代码:
namespace Study.ConsoleCore { //定义委托 public delegate string[] CompanyDelegate(string name); public static class DelegateService { /// <summary> /// 通过委托来实现根据水厂编码获取水厂名称 /// </summary> /// <param name="name">水厂编码</param> /// <param name="companyDelegate">委托方法参数</param> /// <returns></returns> public static string[] GetName(string name, CompanyDelegate companyDelegate) { string[] fullName = companyDelegate(name); return fullName; } /// <summary> /// 根据简称获取企业名称(胜利油田) /// </summary> public static string[] GetSlytNameByShortName(string shortName) { return new string[] { "胜利油田" }; } /// <summary> /// 根据简称获取企业名称(中原油田) /// </summary> public static string[] GetZyytNameByShortName(string shortName) { return new string[] { "中原油田" }; } } }
string name = "slyt"; CompanyDelegate company = DelegateService.GetSlytNameByShortName; //第一种写法 string[] fullNameDelegate1 = DelegateService.GetName(name, company); Console.WriteLine($"使用委托1:{fullNameDelegate1[0]}"); //第二种写法 string[] fullNameDelegate2 = company(name); Console.WriteLine($"使用委托2:{fullNameDelegate2[0]}");
- 我们现在对委托做一个总结:委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。