• c#委托之浅析


    前言:

    这章我们将弄懂,委托是什么?有什么作用?在什么样的场景下可以启到什么作用?

        委托适用的场景:当确定处理一个任务时,不确定其处理任务的方法时可使用,这样可以提高扩展性,调用符合条件的处理方法,避免在程序中大量使用If-Else(Switch)语句。

         大家去网上查询委托相关资料都会出现:

                                                               委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,

                                                 可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

    那么接下来我们一起来解析这段话。

    1、委托是个类:

                     delegate关键字声明委托时,编译器自动为我们生成类。类的名字即为委托变量名,访问类型为定义的委托访问类型。如例中,publice delegate void  TestDelegate(),

    那么编译器就会解析为我们生成一个类名为TestDelegate,访问修饰符类型为publice的类该类继承自[mscorlib]System.MulticastDelegate,任何委托都继承自[mscorlib]System.MulticastDelegate。

    2、定义方法类型:

                        是一种定义方法签名的类型。 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。 相同的方法签名,即参数个数,类型相同,返回值类型相同,所以说委托定义方法的类型。

                           

    这里我们定义了一个返回值为空,带一个string类型参数的委托,当我们实例化委托时,开发工具会提示Test委托需要一个无返回值、带一个string类型参数的方法,否则无法实例化。

    方法不必与委托签名完全匹配(可以先不管,等我们先弄懂委托后,再去看委托的签名,研究方法与委托的关系)

                                   有关更多信息,请参见 在委托中使用变体(C# 和 Visual Basic)。,引用MSDN中对委托中的协变的解析,当委托方法的返回类型具有的派生程度比委托签名更大时,就称为协变委托方法。因为方法的返回类型比委托签名的返回类型更具体,所以可对其进行隐式转换。这样该方法就可用作委托。协变使得创建可被类和派生类同时使用的委托方法成为可能。请参见http://www.docin.com/p-69978094.html。

    3、将方法当作另外一个方法的参数来进行传递:

                    

      class Program
        {
            static void Main(string[] args)
            {
                MinisterReturns t = new MinisterReturns();
                //实例化一个委托(将签名相同的方法作为参数)
                ConsoleApplication2.MinisterReturns.Testdelegate test = new MinisterReturns.Testdelegate(t.Wite);
                t.Dele(test, "q1111111");
                Console.ReadLine();
    
            }
        }
        public class MinisterReturns
        {
            public delegate void Testdelegate(string name);
            //签名方法
            public void Wite(string name)
            {
                Console.WriteLine(name);
            }
            /// <summary>
            /// 调用委托函数
            /// </summary>
            /// <param name="obj">委托函数类型</param>
            /// <param name="name">名称</param>
            public void Dele(Testdelegate obj, string name)
            {
                obj(name);//调用委托签名方法进行处理
            }
    
        }

       运行结果:q1111111

     4、可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性:

                           接下来我们可以用一个经典的案例来演示一下,案例情景:不同国家的人说不同的语言。

                          首先我们先创建一个Speak说话类,里面有个枚举类型,里面包含三个国家,分别是中,英,法,三个说话的方法。

      //说话类
        public class Speak 
        {
    
            //国家
           public   enum Language
            {
                China, America, France
            }
            public void SpeakChinese(string name)
            {
                Console.WriteLine(name+"在说汉语");
            }
            public void SpeakEnglish(string name) 
            {
                Console.WriteLine(name+"在说英语");
            }
            public void SpeakFrench(string name)
            {
                Console.WriteLine(name+"在说法语");
            }
            public void SpeakLanguage(string name, Language language) 
            {
               //判断说那种语言
                switch (language)
                {
                    case Language.China: SpeakChinese(name); break;
                    case Language.America: SpeakEnglish(name); break;
    
                    case Language.France: SpeakFrench(name); break;
    
                }
            }
        }
      
            static void Main(string[] args)
            {
                Speak sp1 = new Speak();
    //实例化委托 sp1.SpeakLanguage(
    "aa", Speak.Language.China); sp1.SpeakLanguage("bb", Speak.Language.America); sp1.SpeakLanguage("cc", Speak.Language.France); Console.ReadLine(); }

    运行结果:

                       aa在说汉语
                       bb在说英语
                       cc在说法语

            现在我们实现了不同国家的人说不同的语言,上面一共有三个国家,如果我还想添加一个国家,需要在Language方法里面添加一个国家,在创建一个说这种语言的方法,还要在switch里面添加一个判断 ,如果添加100种就要判断100次,最后导致代码量多,降低效率。我们这时候就要尝试换个角度去看问题,首先我们需要实现不同国家的人说不同的语言,那么我们的任务就是说话,条件就是不同国家的人说不同的语言,实现说不同的语言就有不同的说话方法(方法不确定)。所以我们可以想到这种场景适合用委托实现。

            首先我们先添加一个委托因为需要分辨不同的人,所以添加一个姓名参数。

    public delegate void SpeakLanuageDelegate(string name);

    我们将之前的SpeakLanguage方法修改一下。

            /// <param name="name">姓名</param>
            /// <param name="languagedelegate">委托类型</param>
            public void SpeakLanguage(string name, SpeakLanuageDelegate languagedelegate)
            {
                languagedelegate(name);
            }

        接着删除Language枚举,将我们之前的Main方法修改一下,实现将方法当作参数传递给另外一个方法。 

           static void Main(string[] args)
            {
          

    Speak sp1 = new Speak();
    //实例化委托 sp1.SpeakLanguage(
    "aa", new Speak.SpeakLanuageDelegate(sp1.SpeakChinese)); sp1.SpeakLanguage("bb", new Speak.SpeakLanuageDelegate(sp1.SpeakEnglish)); sp1.SpeakLanguage("cc", new Speak.SpeakLanuageDelegate(sp1.SpeakFrench)); Console.ReadLine();
    }

    运行结果和上次的一样,现在我们可以发现,代码变得更简洁,修改后的代码比之前更具有扩展性。当我们添加新的国家时只需创建一个实现该语言说话的方法,然后实例化一下就行。

              -------------------有误之处望指点,共勉。

            

            

  • 相关阅读:
    JSON.parse(JSON.stringify()) 实现对对象的深拷贝
    Promise 多重链式调用
    qs.parse() 和 qs.stringfy() 之 传输数据秘籍
    js 递归思想 处理后台多维数组的数据 之 完美契合
    js 反转字符串的实现
    js 中的! 和 !! 的区别
    vue 权限管理深度探究
    Web 前端 中高难度问题(希望看完之后的你可以拿到Offer^v^)
    vue懒加载 路由 router 的编写(resolve)
    Efficiency in Shell
  • 原文地址:https://www.cnblogs.com/wdht/p/9531191.html
Copyright © 2020-2023  润新知