小小程序员,大大发财梦

撒贝宁说:你读一篇文章疑问越多,就代表你需要成长的空间越大。

【个人学习】: 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)语句,同时使得程序具有更好的可扩展性。

 

 

 

 

posted @ 2019-11-22 15:32  敲代码使我秃了头  阅读(153)  评论(0编辑  收藏  举报