zoukankan      html  css  js  c++  java
  • 委托学习笔记1:委托的基本使用

    一、引子

    在正式说委托前,我先给一个例子,然后引出后面要说的委托。

    很简单,就是一个机器人打招呼的。

    代码清单1.1

        class Robot
        {
            public void GreetByChinese(string name)
            {
                Console.WriteLine("你好," + name + "!");
            }
            public void GreetByEnglish(string name)
            {
                Console.WriteLine("Hello," + name + "!");
            }
            //打招呼
            public void DoGreet(string name,string lang)
            {
                switch (lang)
                {
                    case "chinese":
                        GreetByChinese(name);
                        break;
                    case "english":
                        GreetByEnglish(name);
                        break;
                    default: break;
                }
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                //实例化机器人对象
                Robot robot = new Robot();
                string name = Console.ReadLine();
                robot.DoGreet(name,"chinese");
                robot.DoGreet(name,"english");
                Console.Read();
            }
            
        }
    View Code

    代码清单1.1中创建了一个机器人类,类中封装了两个打招呼的方法和一个调用这两个方法的公共方法。DoGreet方法中,只要带nameswitch中的条件,就可以打印出对应语言打招呼的语句。

    那么,如果我要增加其他的语言,如法语、日语、韩语等,我除了增加对应的方法,还需要改DoGreet方法里的case语句,维护量较大。那有什么办法可以解决这种尴尬呢?

    一种比较简单的方法是,直接将方法作为参数(变量),传给另一个方法(DoGreet),在其中执行即可。

    但我们都知道,能作为方法的参数的是某一类型的对象或变量,而方法是个什么类型呢?确实找不出方法对应的类型。但依然有种方法可以间接的将方法作为一个参数来使用,这便引出了,下面要提到的“委托”。 

    二、关于委托,微软给出的定义如下:

    “委托用于将方法作为参数传递给其他方法。”

    早在C#1.0时,就已开始支持这个特性(用过VS2003的园友,应该是最清楚不过了)。关于微软给出的定义,已经很好理解了:我们利用委托,把方法作为一个参数(变量)传递给其他的方法,从而由其他方法来代为执行这个当做参数的方法里的动作。 

    三、那么怎么去使用委托呢?

    使用委托,基本要按照如下步骤实现:

    1、定义一个委托类型

    访问修饰符 delegate 返回类型 委托类型名称(参数列表);

    Expublic delegate void Greet(string name);

    2、创建一个执行某动作的方法(返回类型和参数列表须与委托类型相同)

    访问修饰符 返回类型 方法名称(参数列表){......}

    Expublic void GreetByChinese(string name)

    {

    Console.WriteLine(“你好,”+name+“!”);

    }

    3、实例化委托类型

    委托类型名称 委托对象名称=方法名称;

    ExGreet greet=GreetByChinese;

    4、开始使用,执行操作

    委托对象名称(参数列表);

    或:委托对象名称.Invoke(参数列表);

    Exgreet(“季节旋风”);  或:greet.Invoke(“季节旋风”); 

    如上,就这么个简单的流程,是不是很简单。但这里,可能有人会说,定义中不是将方法作为参数传给另一个方法吗?怎么没有这么用?其实这个不用担心,我们已经在步骤3中将方法引用给了greet对象,既然是对象,那么久可以作为方法的参数,就可以很好地解决这个疑问。

    具体的看下面的代码清单3.1

        //一个常用的委托,打招呼
        delegate void Greet(string name);
        //一个机器人类,封装打招呼
        class Robot
        {
            public void GreetByChiness(string name)
            {
                Console.WriteLine("你好," + name + "!");
            }
            public void GreetByEnglish(string name)
            {
                Console.WriteLine("Hello," + name + "!");
            }
    public void GreetByJapaness(string name)
    {
    Console.WriteLine("こんにちは," + name + "!");
    }
            //打招呼
            public void DoGreet(string name, Greet greet)
            {
                greet(name);
            }
        }
        class SampleDelegate
        {
            static void Main(string[] args)
            {
                //实例化机器人对象
                Robot robot = new Robot();
                string name = Console.ReadLine();
                //通过把方法作为变量来实现打招呼
                robot.DoGreet(name, robot.GreetByChiness);
                robot.DoGreet(name, robot.GreetByEnglish);
    robot.DoGreet(name, robot.GreetByJapaness);
                Console.Read();
            }
    }
    View Code

    执行结果如下:

     

    依然是机器人大招呼的例子,但用到了委托,这样一来是不是更简洁了?这里已经可以轻松地将方法作为参数传递给执行方法(DoGreet)中,并在其中执行操作。 

    四、合并委托(多路广播委托)

    委托对象的一个有用属性是:可以使用 “+” 运算符将多个对象分配给一个委托实例。 多播委托包含已分配委托的列表。 在调用多播委托时,它会按顺序调用列表中的委托。 只能合并相同类型的委托。 “-” 运算符可用于从多播委托中移除组件委托。

    依然用机器人打招呼的例子来讲,这里就不再使用DoGreet方法了,直接在Main方法中来做“打招呼”动作。如下(代码清单4.1):

    Greet greet = robot.GreetByChiness;
    greet += robot.GreetByEnglish;
    greet += robot.GreetByJapaness;
    greet(name);

    在运行时,它会按顺序执行调用的方法,如下图:

    值得注意的是,只有对委托对象greet初始化后才可进行多播操作,例如下面的这种写法就是错误的:

    Greet greet+= robot.GreetByChiness;

    在执行移除(“-”)操作时,跟合并操作类似,但它是从委托中移除已有的方法。例如将代码清单4.1的代码后面加上,下面代码(代码清单4.2):

    Console.WriteLine("移除日语后:");
    greet -= robot.GreetByJapaness;
    greet(name);

    那么第二次greet时,会少一个日语问候,执行结果如下图:

  • 相关阅读:
    BZOJ3073 Journeys
    UOJ261 【NOIP2016】天天爱跑步 LCA+动态开点线段树
    [bzoj2654] tree 最小生成树kruskal+二分
    【ZJOI2007】【BZOJ1059】矩阵游戏 匈牙利算法
    [Bzoj 2427] [HAOI2010] 软件安装 tarjan缩点+树形DP
    [CQOI2011]放棋子--DP
    BZOJ 3990 排序
    (六)接入层:反向代理,接入层扩容,负载均衡
    (五)伪分布式:你以为,多机就是分布式?
    (四)容量设计:流量高低,对架构究竟有什么影响?
  • 原文地址:https://www.cnblogs.com/jijiexuanfeng/p/4439150.html
Copyright © 2011-2022 走看看