`
coconut_zhang
  • 浏览: 543716 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

深入理解C#中的委托和事件:委托的定义

阅读更多

委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、委托和事件对Observer设计模式的意义、.Net Framework中的委托和事件,对它们的中间代码也做了讨论。
  将方法作为方法的参数
  我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语:
public void GreetPeople(string name) {
// 做某些额外的事情,比如初始化之类,此处略
EnglishGreeting(name);
}
public void EnglishGreeting(string name) {
Console.WriteLine("Morning, " + name);
}  暂且不管这两个方法有没有什么实际意义。GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说"Jimmy",进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting则用于向屏幕输出 "Morning, Jimmy"。
  现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白"Morning"是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法:
public void ChineseGreeting(string name){
Console.WriteLine("早上好, " + name);
}  这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:
public enum Language{
English, Chinese
}

public void GreetPeople(string name, Language lang){

//做某些额外的事情,比如初始化之类,此处略
swith(lang){
case Language.English:
EnglishGreeting(name);
break;
case Language.Chinese:
ChineseGreeting(name);
break;
}
}  OK,尽管这样解决了问题,但我不说大家也很容易想到,这个解决方案的可扩展性很差,如果日后我们需要再添加韩文版、日文版,就不得不反复修改枚举和GreetPeople()方法,以适应新的需求。

 

在考虑新的解决方案之前,我们先看看GreetPeople的方法签名:
public void GreetPeople(string name, Language lang)  我们仅看 string name,在这里,string 是参数类型,name 是参数变量,当我们赋给name字符串"jimmy"时,它就代表"jimmy"这个值;当我们赋给它"张子阳"时,它又代表着"张子阳"这个值。然后,我们可以在方法体内对这个name进行其他操作。哎,这简直是废话么,刚学程序就知道了。
  如果你再仔细想想,假如GreetPeople()方法可以接受一个参数变量,这个变量可以代表另一个方法,当我们给这个变量赋值 EnglishGreeting的时候,它代表着 EnglsihGreeting() 这个方法;当我们给它赋值ChineseGreeting 的时候,它又代表着ChineseGreeting()方法。
  我们将这个参数变量命名为 MakeGreeting,那么不是可以如同给name赋值时一样,在调用 GreetPeople()方法的时候,给这个MakeGreeting 参数也赋上值么(ChineseGreeting或者EnglsihGreeting等)?然后,我们在方法体内,也可以像使用别的参数一样使用 MakeGreeting。但是,由于MakeGreeting代表着一个方法,它的使用方式应该和它被赋的方法(比如ChineseGreeting) 是一样的,比如:
MakeGreeting(name);  好了,有了思路了,我们现在就来改改GreetPeople()方法,那么它应该是这个样子了:
public void GreetPeople(string name, *** MakeGreeting){
MakeGreeting(name);
}  注意到 *** ,这个位置通常放置的应该是参数的类型,但到目前为止,我们仅仅是想到应该有个可以代表方法的参数,并按这个思路去改写GreetPeople方法,现在就出现了一个大问题:这个代表着方法的MakeGreeting参数应该是什么类型的?
  NOTE:这里已不再需要枚举了,因为在给MakeGreeting赋值的时候动态地决定使用哪个方法,是ChineseGreeting还是 EnglishGreeting,而在这个两个方法内部,已经对使用"morning"还是"早上好"作了区分。
  聪明的你应该已经想到了,现在是委托该出场的时候了,但讲述委托之前,我们再看看MakeGreeting参数所能代表的 ChineseGreeting()和EnglishGreeting()方法的签名:
public void EnglishGreeting(string name)
public void ChineseGreeting(string name)  如同name可以接受String类型的"true"和"1",但不能接受bool类型的true和int类型的1一样。MakeGreeting的 参数类型定义 应该能够确定 MakeGreeting可以代表的方法种类,再进一步讲,就是MakeGreeting可以代表的方法 的 参数类型和返回类型。

 

于是,委托出现了:它定义了MakeGreeting参数所能代表的方法的种类,也就是MakeGreeting参数的类型。
  NOTE:如果上面这句话比较绕口,我把它翻译成这样:string 定义了name参数所能代表的值的种类,也就是name参数的类型。
  本例中委托的定义:
public delegate void GreetingDelegate(string name);  可以与上面EnglishGreeting()方法的签名对比一下,除了加入了delegate关键字以外,其余的是不是完全一样?
  现在,让我们再次改动GreetPeople()方法,如下所示:
public void GreetPeople(string name, GreetingDelegate MakeGreeting){
MakeGreeting(name);
}  如你所见,委托GreetingDelegate出现的位置与 string相同,string是一个类型,那么GreetingDelegate应该也是一个类型,或者叫类(Class)。但是委托的声明方式和类却完全不同,这是怎么一回事?实际上,委托在编译的时候确实会编译成类。因为Delegate是一个类,所以在任何可以声明类的地方都可以声明委托。更多的内容将在下面讲述,现在,请看看这个范例的完整代码:
using System;
using System.Collections.Generic;
using System.Text;

namespace Delegate {
//定义委托,它定义了可以代表的方法的类型
public delegate void GreetingDelegate(string name);


class Program {

private static void EnglishGreeting(string name) {
Console.WriteLine("Morning, " + name);
}

private static void ChineseGreeting(string name) {
Console.WriteLine("早上好, " + name);
}

//注意此方法,它接受一个GreetingDelegate类型的方法作为参数
private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {
MakeGreeting(name);
}

static void Main(string[] args) {
GreetPeople("Jimmy Zhang", EnglishGreeting);
GreetPeople("张子阳", ChineseGreeting);
Console.ReadKey();
}
}
}  输出如下:
  Morning, Jimmy Zhang
  早上好, 张子阳
  我们现在对委托做一个总结:
  委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

分享到:
评论
2 楼 coconut_zhang 2012-05-27  
tangchenghai 写道
还是不明白你这样调用
GreetPeople("Jimmy Zhang", EnglishGreeting);
GreetPeople("张子阳", ChineseGreeting);

和直接这样调用:
EnglishGreeting("Jimmy Zhang");
ChineseGreeting("张子阳");

有什么区别?也没有所说的;可以避免在程序中大量使用If-Else(Switch)语句,求解


这只是一个例子,说明一下委托。个人感觉,这样做的好处是,具有相同签名的方法有相同的接口。如果都直接调用,1000个方法要1000个对外的接口,这是不是太多了。如果采用上面If-Else那段代码的形式,这个问题是可以解决,但是如果隔三差五的加个方法,还要每次都更改GreetPeople方法,如果不是一个人写的,就更完了,还要改别人的方法。
1 楼 tangchenghai 2012-05-14  
还是不明白你这样调用
GreetPeople("Jimmy Zhang", EnglishGreeting);
GreetPeople("张子阳", ChineseGreeting);

和直接这样调用:
EnglishGreeting("Jimmy Zhang");
ChineseGreeting("张子阳");

有什么区别?也没有所说的;可以避免在程序中大量使用If-Else(Switch)语句,求解

相关推荐

    C#中委托与事件的区别

    委托(Delegate)和事件(Event)是C#中非常重要的两种机制,它们在.NET框架中扮演着极其重要的角色。理解这两种概念,对于深入学习C#编程语言,构建高效、可维护的程序架构至关重要。首先我们来探讨一下委托的概念...

    C#--委托和事件

    ### C#中的委托和事件 #### 一、委托的基础概念 在C#中,委托是一种引用类型的...事件和委托机制极大地简化了事件处理过程,使得程序设计更加灵活和模块化。希望本文能够帮助大家更好地理解和掌握C#中的事件编程。

    C#事件和委托定义与使用(有两个很形象的例子)

    本文将深入探讨C#中的两个关键概念:事件和委托,并通过实例进行详细解析,帮助初学者更好地理解和运用。 首先,我们来了解什么是委托。在C#中,委托是一种类型,它代表了方法的引用,类似于函数指针。委托可以被视...

    C#委托事件-张子阳.pdf

    本文将以“C#委托事件-张子阳.pdf”这份资料为基础,深入探讨委托和事件的基础知识、应用场景以及它们在.NET Framework中的具体实现方式。 #### 二、委托的基本概念 **1. 为什么需要委托** 在前面的例子中,我们...

    C# 中的委托和事件

    本文将深入探讨C#中的委托和事件的概念及其应用,并通过具体示例来帮助理解这些核心概念。 #### 二、委托的基本概念 ##### 2.1 委托定义 - **委托**是一种引用类型的数据结构,它用来封装方法的引用。 - 它可以...

    c#中委托,事件和BeginInvoke在进程间传递消息的作用

    委托、事件和BeginInvoke在C#中是实现进程间消息传递的重要概念和工具。委托可以理解为一个可以持有对具有特定参数列表和返回类型的方法的引用的类型。事件是一种特殊的委托,用于实现发布-订阅模式,其中发布者触发...

    对C#委托及事件委托的理解

    本文将深入探讨C#中的委托和事件委托的概念、用途以及它们的工作原理。 1. **委托的定义**: 委托在C#中是一种类型,它类似于函数指针,但比函数指针更安全,因为它是类型安全的。声明委托时,我们需要使用`...

    C# 委托和事件 (详细讲解)

    在C#编程语言中,委托和事件是两个关键的概念,它们是实现面向对象设计模式,尤其是事件驱动编程的核心。下面将详细阐述这两个概念及其在实际编程中的应用。 **委托** 委托在C#中相当于一种类型,它封装了指向方法...

    详解C#委托,事件与回调函数

    详解 C# 委托、事件与回调函数 委托是 C# 中一种非常重要的概念,它可以将方法作为参数传递给其他方法,也可以将方法作为...委托、事件和回调函数是 C# 中三个非常重要的概念,它们在编程中扮演着非常重要的角色。

    c#委托和事件教程,委托事件教程

    总的来说,委托和事件是C#中实现回调和异步编程的关键工具,它们使得代码更加灵活,能够更好地响应外部事件和用户交互。理解和熟练使用委托和事件对于开发高效、可维护的.NET应用程序至关重要。在实际编程中,它们常...

    C#中的委托和事件.pdf

    委托和事件是C#编程语言中非常重要的两个概念,它们是.NET框架中实现解耦合、异步编程以及观察者设计模式的基础。委托(Delegate)是一种特殊的数据类型,用于封装一个方法的引用。在C#中,委托声明了可以被调用的...

    C# 中的委托和事件 详解

    事件和委托是实现观察者模式的一种方式。 在上面的例子中,`Greeter`类作为主题(Subject),`GreetingEvent`作为主题发布的一个事件。`EnglishGreeting`和`ChineseGreeting`方法作为观察者(Observer),它们通过订阅...

    C#中委托和事件,无多播委托

    本文将深入探讨C#中的委托、事件以及无多播委托的概念,并通过具体示例帮助读者更好地理解和应用这些概念。 #### 委托 委托是一种引用类型的数据结构,它允许我们将方法作为参数传递给其他方法。简而言之,委托...

    C# 事件委托简单封装示例

    在C#编程中,事件和委托是核心特性之一,它们为构建可扩展和灵活的代码提供了基础。事件委托的封装是提高代码复用性和模块化的重要手段。本示例将探讨如何在C#中实现事件委托的简单封装,并提供一个实际的应用场景。...

    C#中委托和事件 方法的使用

    这里的`Greeting`委托定义了一个无返回值的参数为`string`的方法。这样,我们就可以创建`Greeting`类型的委托实例,并将其指向具体的方法: ```csharp Greeting makeGreeting = EnglishGreeting; makeGreeting(...

    c#委托与事件的关系

    在面向对象编程语言C#中,委托(Delegate)和事件(Event)是两个重要的概念。本文将深入探讨这两者之间的关系及其在实际开发中的应用。 #### 二、委托(Delegate) 1. **定义**: - 委托在C#中类似于C++中的函数...

    C# 利用委托和事件在窗口间传递参数

    在C#编程中,委托和事件是两种非常重要的特性,它们在处理对象间的通信和响应机制上发挥着关键作用。特别是在开发Windows Form应用程序时,利用委托和事件可以在窗口之间有效地传递参数,实现用户界面的交互。本文将...

Global site tag (gtag.js) - Google Analytics