将方法作为方法的参数 —— 理解委托

《.NET开发之美》上对于委托写到:“它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别得慌,混身不自在。”我觉得这句话就像是在说我自己一样。于是我决定好好看看关于这方面的知识。

一、委托与接口

其实很多时候我感觉委托所起的作用与定义一个只是含有一个方法的接口完全一样的,他们实现的功能是相同的。

假设有这样一个例子:

其实这个例子很简单,就是定义了一个IGreeting接口,里面有一个Greetingpeople方法,EnglishGreeting和ChineseGreeting都是通过实现这个接口来显示的。

如果通过委托应该怎么样实现呢?

二、将方法作为方法的参数

刚才的功能如果正常我们会选择以下方法来实现:

        public void GreetPeople(string name, Language lang)
        {
            //做某些额外的事情,比如初始化之类,此处略
            switch (lang)
            {
                case Language.English:
                    EnglishGreeting(name);
                    break;
                case Language.Chinese:
                    ChineseGreeting(name);
                    break;
            }
        }
        public void EnglishGreeting(string name)
        {
            Console.WriteLine("Morning, " + name);
        }
        public void ChineseGreeting(string name)
        {
            Console.WriteLine("早上好, " + name);
        }
        public enum Language//enum为枚举函数
        {
            English, Chinese
        }
        static void Main(string[] args)
        {
            GreetPeople("Jimmy Zhang", Language .English );
            Console.ReadKey();
        }

但是这样的方法需要我们反复修改枚举和GreetPeople()方法,以适应新的需求。

如果你再仔细想想,假如GreetPeople()方法可以接受一个参数变量,这个变量可以代表另一个方法,当我们给这个变量赋值 EnglishGreeting的时候,它代表着 EnglsihGreeting() 这个方法;当我们给它赋值ChineseGreeting 的时候,它又代表着ChineseGreeting()方法。我们将这个参数变量命名为 MakeGreeting,那么不是可以如同给name赋值时一样,在调用 GreetPeople()方法的时候,给这个MakeGreeting 参数也赋上值么(ChineseGreeting或者EnglsihGreeting等)?然后,我们在方法体内,也可以像使用别的参数一样使用 MakeGreeting。但是,由于MakeGreeting代表着一个方法,它的使用方式应该和它被赋的方法(比如ChineseGreeting) 是一样的,比如:MakeGreeting(name)。

按照上面的思路,

Public void EnglishGreeting(string name)

public void ChineseGreeting(string name)

string 定义了name参数所能代表的值的种类,也就是name参数的类型。于是,委托出现了:它定义了MakeGreeting参数所能代表的方法的种类,也就是MakeGreeting参数的类型。

于是,从图中可以看出,生命了GreetingDelegate: public delegate void GreetingDelegate(string name)。并且,在greetpeople 方法中,MakeGreeting方法作为参数与name地位是一样的。代码如下:

 private static void GreetPeople(string name, GreetingDelegate MakeGreeting)
        {
            MakeGreeting(name);
        }

同理,而既然委托GreetingDelegate 和 类型 string 的地位一样,都是定义了一种参数类型,那么,我是不是也可以这么使用委托?

static void Main(string[] args) {
    GreetingDelegate delegate1, delegate2;
    delegate1 = EnglishGreeting;
    delegate2 = ChineseGreeting;

    GreetPeople("Jimmy Zhang", delegate1);
        GreetPeople("张子阳", delegate2);
        Console.ReadKey();
时间: 2024-10-27 18:37:41

将方法作为方法的参数 —— 理解委托的相关文章

C# 委托系列(一)将方法作为方法的参数

http://t.qq.com/baijialeyi6756 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在.本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.事件的由来.委托和事件对Observer设计模式的意义..Net Framework中的委托和事件,对它们的中间代

C#Lambda表达式的理解:谓词方法 匿名方法 使用Lambda

Lambda表达式 "Lambda表达式"是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量.它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式.所有Lambda表达式都使用Lambda运算符=>,该运算符读作"goes to".Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块. 下面三个方法会帮你会容易理解到Lambda表达式的好处,

重命名(方法,类,参数)

概念:本文中的改名(方法,类,参数)是指在写代码的时候对类.方法.参数.委托.事件等等元素取一个有意义的名称. 正文:如下代码所示,加入一个公司建立一个员工的类,类中有一个员工名字的字段和一个按照小时计算员工收入的方法,那么下面代码的取名就显得很难理解了,所以我们会重构名称. namespace LosTechies.DaysOfRefactoring.Rename.Before { public class Person { public string FN { get; set; } pub

js中sort()方法的用法,参数以及排序原理

sort() 方法用于对数组的元素进行排序. 语法:arrayObject.sort(sortby):参数sortby可选.规定排序顺序.必须是函数. 注:如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序.要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较. 如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字.比较函数应该具有两个参数 a 和 b,其返回

c#方法重载,可选参数,命名参数。

其实这里没什么可说哦,c++的语法大同小异.先看一段代码. class Program { public static void Test(int a) { Console.WriteLine("只有一个参数a=={0}", a); } public static void Test(int a, int b = 5) { Console.WriteLine("有两个参数a=={0},b=={1}", a, b); } static void Main() { Te

定义一个方法get_page(url),url参数是需要获取网页内容的网址,返回网页的内容。提示(可以了解python的urllib模块)

1 定义一个方法get_page(url),url参数是需要获取网页内容的网址,返回网页的内容.提示(可以了解python的urllib模块) 2 import urllib.request 3 4 def get_page(url): 5 response = urllib.request.urlopen(url) 6 html = response.read() 7 return html 8 9 print(get_page(url='https://www.baidu,com'))

使用getParameterMap()方法实现对请求参数的封装的工具类

我们知道,HttpServletRequest这个类的getParameter(name),getParameterValues(name)可以分别实现对页面传来的单个参数和对多个同名参数的接受.特别是getParameter(name)这个方法被用的次数特别多.有时候页面传来多个参数的情况下,要写多个request.getParameter(name)进行逐个接受,当然在springmvc框架下你可以在选择使用对象接受参数,也可以在方法上对参数进行逐个接收.但这样做的弊端在于在请求参数个数和名

wrong number of arguments,java方法反射时数组参数的坑

java方法中只有一个参数是数组,反射的时候我们不能想当然的传歌数组进去,传数组进去的时候表示多个参数. 两个数组不是一个意思啊. 我们应该把数组转为objet,这样才表示一个参数. import java.lang.reflect.Method; public class MethodTest { public void a(String[] args) { System.out.println("a"); } public static void main(String[] arg

JAVA EE 项目经常使用知识 之AJAX技术实现select下拉列表联动的两种使用方法(让你真正理解ajax)

ajax 下拉列表联动的使用方法. ajax的定义: AJAX 是一种用于创建高速动态网页的技术. 通过在后台与server进行少量数据交换,AJAX 能够使网页实现异步更新.这意味着能够在不又一次载入整个网页的情况下,对网页的某部分进行更新. ajax效果的一个样例: 区域为空的时候,维护人情况: 选了一个区域后的情况:(选 舒城县 联带出来的维护人员 小刘) 一.原生态的js实现 XMLHttpRequest 是 AJAX 的基础 XMLHttpRequest 对象 全部现代浏览器均支持 X