一、在控制台下使用委托和事件

我们都知道,C#中有“接口”这个概念,所谓的“接口”就是定义一套标准,然后由实现类来具体实现其中的方法,所以说“接口,是一组类的抽象”。同样道理,我们可以将“委托”理解为“方法的抽象”,也就是说定义一个方法的模板,至于这个方法具体是怎么样的,就由方法自己去实现。

我们知道接口的最大好处就是可以实现多态,同理,“委托”是可以实现方法的多态,当我们想调用某个具体方法的时候,我们不直接调用这个方法,而是去调用这个委托。当然,我们必须在具体方法和委托之间建立某种关联。

下面我们来看例子。

首先,我们定义一个委托:

public delegate void SaySomething(string name);

这跟抽象方法的语法格式很相似,只是多了一个关键字delegate。既然是对方法的一种抽象,那么我们最关注的当然就是方法的返回值以及方法的参数了。所以上面红色的部分就是我们定义出来的一个规矩,如果某个方法想委托我去做事,那么请你遵循我的规矩,就是返回值为void,参数为一个字符串。我们这个委托的含义是,当某个人来了,就向他说点东西。

好,既然我们已经定义了这个规矩,下面我们就定义具体的方法了。

public void SayHello(string name)
{
    Console.WriteLine("Hello," + name + "!");
}

public void SayNiceToMeetYou(string name)
{
    Console.WriteLine("Nice to meet you," + name + "!");
}

我们这里一共定义了两个方法,一个是向某人说Hello,另一个是向某人说Nice to meet you。我们看到,这里定义的两个方法的返回值和参数跟我们前面定义的“委托”是一致的。

接下来,我们来看事件。

public event SaySomething come;

我们定义了一个事件,这个事件是“有人来了”,注意定义的时候我们使用event关键字,除此之外,我们还加上了前面定义的“委托”的名字。这个意思是说,我这个事件只会跟“SaySomething”打交道,并且,当我这个事件发生的时候,我会通知关注我的这些“委托”(再由这些“委托”去调用具体的方法)。

我们来定义一个测试方法:

public void test() { 
    SaySomething sayhello = new SaySomething(SayHello);
    SaySomething saynice = new SaySomething(SayNiceToMeetYou);
    come += sayhello;
    come += saynice;
    come("张三");
}

方法体中的前面两行是用来实例化委托,注意我们用到了new关键字,就好像实例化一个类一样,然后传入一个参数,但这个参数不是string类型、也不是int类型,而是一个方法名。

再下面两行就是将委托加到事件上,意思是说,如果你这个事件发生了,就告诉我一声。可以通过“+=”来将n个委托实例加到某个事件上,一旦这个事件发生,所有的这些委托实例都会得到通知。

最后一行是触发一个事件,注意我们是直接用一个事件名,然后跟一个参数,这又跟“委托”中定义的那个规矩一致(即,要有一个string类型的参数)。

最后运行一下

static void Main(string[] args)
{
    Program program = new Program();
    program.test();
    Console.Read();
}

我们回过头来再看一下“事件”的定义:

public event SaySomething come;

这里已经指出了“委托”的名字,所以,我们可以直接将方法加到事件上,而省略“委托”的实例化过程,因此上面的test()方法可以简单写为:

public void test() { 
    come += SayHello;
    come += SayNiceToMeetYou;
    come("张三");
}

二、在窗体中使用委托和事件

上面的例子并不能体现委托和事件的优点,其实,委托和事件在C#中使用非常广泛,例如,当我们点击某个“按钮”的时候,就会有一个“Click”事件触发,而这个事件会通知“委托”,在C#窗体应用程序中,“委托”的名字比较规范,统一使用“EventHandler”,它的具体格式是“void EventHandler(object sender, EventArgs e);”。相信大家都写过下面这样子的HelloWorld程序:

当点击按钮的时候弹出一个对话框。我们怎样实现的呢?你肯定会说,我们在设计窗口双击按钮,就会自动为我们生成类似如下的方法:

private void button1_Click(object sender, EventArgs e)
{
    MessageBox.Show("我被点击了!!!");
}

其实,这里用到的就是事件和委托,这里的button1_Click就是符合EventHandler委托规矩的一个具体的方法,即返回值为void,参数分别是一个object和EventArgs。

我们可以在Form1.Designer.cs中看到如下代码:

this.button1.Click += new System.EventHandler(this.button1_Click);

可以看到,这里有一个Click事件,然后将一个委托实例附加到这个事件上,跟我们前面讲的控制台应用程序中的用法是完全一样的。那这个Click事件是怎么触发的呢?对于这些系统类的事件,并不用我们管。

当然,我们也可以定义自己的事件和委托,例如我定义一个事件,这个事件就是输出对象的名字。

我们这里定义了一个ShowName委托和一个btnclick事件。并且,在button1_Click()方法中触发这个btnclick事件。最后的结果是,当我们点击按钮的时候,首先弹出一个“我被点击了!!!”的对话框,然后确定之后再弹出另一个显示按钮名称的对话框:

http://ruizhinet.blog.163.com/blog/static/9921382820092801032681/

http://ruizhinet.blog.163.com/blog/static/99213828200901110564999/

C#委托与事件的更多相关文章

  1. .NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...

  2. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  3. [转载]C#深入分析委托与事件

    原文出处: 作者:风尘浪子 原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 同类链接:http://www.c ...

  4. [转载]C#委托和事件(Delegate、Event、EventHandler、EventArgs)

    原文链接:http://blog.csdn.net/zwj7612356/article/details/8272520 14.1.委托 当要把方法作为实参传送给其他方法的形参时,形参需要使用委托.委 ...

  5. C#委托与事件的简单使用

    前言:上一篇博文从原理和定义的角度介绍了C#的委托和事件.本文通过一个简单的小故事,来说明C#委托与事件的使用方法及其方便之处. 在阅读本文之前,需要你对委托和事件的基本概念有所了解.如果你是初次接触 ...

  6. C#之委托与事件

    委托与事件 废话一堆:网上关于委托.事件的文章有很多,一千个哈姆雷特就有一千个莎士比亚,以下内容均是本人个人见解. 1. 委托 1.1 委托的使用 这一小章来学习一下怎么简单的使用委托,了解一些基本的 ...

  7. [ASP.NET MVC 大牛之路]02 - C#高级知识点概要(1) - 委托和事件

    在ASP.NET MVC 小牛之路系列中,前面用了一篇文章提了一下C#的一些知识点.照此,ASP.NET MVC 大牛之路系列也先给大家普及一下C#.NET中的高级知识点.每个知识点不太会过于详细,但 ...

  8. .NET委托和事件

    .net学习之委托和事件   1.什么是委托 通俗的说:委托就是一个能够存储符合某种格式(方法签名)的方法的指针的容器 上传图片: 2.委托语法 准备一个方法:string Hello(string ...

  9. C#委托和事件

    委托和事件都可以用来调用跟自己方法签名一样的方法,两者在使用中主要有以下区别: 委托和事件没有可比性,因为委托是类型,事件是对象: 委托可以在声明它的类外部进行调用,而事件只能在类的内部进行调用: 委 ...

随机推荐

  1. Jsp语法简介

    1.JSP指令 jsp指令用来设置整个JSP网页想关闭的属性,如网页的编码和脚本语言等.常用的3种指令为page,include和taglib. 2.JSP声明 jsp声明用于声明JSP代表的Serv ...

  2. tomcat 504 gateway time-out

    今天有个环境ajax调用一个请求的时候,出现一个504 gateway time-out响应,原以为是nginx找不到资源的问题,恰当我们的服务器上又配置了nginx,看了配置文件,没有指向tomca ...

  3. css3制作炫酷导航栏效果

    今天主要利用hover选择器.鼠标滑过查看效果. 一.普通导航栏 Home Content Service Team Contact 对于这种普通的导航栏,只是鼠标滑过的时候颜色会变,所以思路变得很简 ...

  4. React Native JSX value should be expression or a quoted JSX text.

    问题描述:  我在使用props时候, 我的写法是这样的 ... <View> <Person name='john' age=32 gender=true></Pers ...

  5. C# List 排序各种用法与比较

    下面介绍各种List的sort的用法与比较 首先,我们建一个People的实体,有name.age.sex的属性,我们要排序的字段是年龄age 新建一个实体类 public class People ...

  6. C#Winform连接Oracle数据库

    转载▼ http://blog.sina.com.cn/s/blog_900ca29d0102vn3r.html 一.连接方法 (1)System.Data.OracleClient 注意1:此方法在 ...

  7. Windows Server 2012 虚拟化实战:存储(二)

    五.搭建Window Server 2012虚拟化的存储网络 前文我们讨论了Window Server 2012支持的各种与存储相关的技术,接下来我们通过实践对其中的一些技术进行检验.实际上Windo ...

  8. CentOS安装Nginx-1.6.2+安全配置

    注:以下所有操作均在CentOS 6.5 x86_64位系统下完成. #准备工作# 在安装Nginx之前,请确保已经使用yum安装了pcre等基础组件,具体见<CentOS安装LNMP环境的基础 ...

  9. STM32C8T6 JTAG使用到PB3|PB4|PA13|PA14|PB15端口做普通IO时,需禁止JTAG!

    GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIO ...

  10. 搭建基于PHP的www服务器

    安装MySQL #!/bin/bash mount |grep "/dev/sr0" if [ "$?" != 0 ];then mount /dev/sr0 ...