您的位置:首页 > 编程语言 > C#

C#中的委托与事件

2015-11-24 18:53 423 查看

委托

我们习惯把数据或者对象作为参数传递给方法,比如:

int i = int.Parse("99");


如果我们把方法作为参数传递给方法,这就需要用到委托了。我们从字面上理解委托,就像是A委托B去办一件事情一样,其实在C#中也有这一层的含义。

首先我们先看C#中的语法:

public delegate void DoSomethingEventHandler();


delegate是关键字,EventHandler算是一个声明委托类型的一个命名标准。委托的定义就这么简单。

让我们先来看一段代码:

class Student {
public static void MakeTea() {
Console.WriteLine("Got it!");
}
}

class Teacher
{
//声明一个委托
public delegate void DoSomething();
static void Main(string[] args)
{
//给委托传递具体方法
DoSomething myDelegate = new DoSomething(Student.MakeTea);
//委托被赋予了具体的方法
myDelegate();

}
}


我们来看一下我们定义的委托和委托被赋予的方法:

public delegate void DoSomething();
public static void MakeTea() {
/..../
}


或许这样比较并看不出什么,毕竟我们对委托还没有具体的认识,所以我们来看一下委托的一些规定:

C#中委托的参数和返回类型,都要和你要具体委托的方法要一致。我们再来看一下委托时如何运作的:

DoSomething myDelegate = new DoSomething(Student.MakeTea);
myDelegate();


或许有C++基础的已经看出来了,委托和C++中的函数指针类似。确实委托就可以看做一个函数指针。所以才会有委托的参数和返回值必须和具体委托的方法一致的规定。

多播委托

多播委托其实也很简单。我们先看代码:

class Student {
public static void MakeTea() {
Console.WriteLine("Got it!");
}

public static void BuyPen() {
Console.WriteLine("On my way");
}
}

class Teacher
{
//声明一个委托
public delegate void DoSomething();
static void Main(string[] args)
{
//给委托传递具体方法
DoSomething myDelegate = new DoSomething(Student.MakeTea);

myDelegate += Student.BuyPen;
//委托被赋予了具体的方法
myDelegate();

}
}


我们看到Student中添加了一个BuyPen的功能,我们只是在程序中加了myDelegate += Student.BuyPen;

这就相当于要做两件事,显示倒茶,然后去买笔。其实是委托中重载了“+=”这个运算符,我们才可以以这种方法创建委托链。相对的我们可以用“-=”来销毁这个委托链。

事件

点击事件,加载事件充斥在我们的日常编程中,我们对事件都有一个模糊的认识。下面我们来看一下比较官方的概念:事件是类在发生其关注的事情时用来提供通知的一种方式。

我们先看一段代码:

/// <summary>
/// 含有姓名和年龄属性,并重写了ToString方法
/// </summary>
class PersonEventArgs:EventArgs
{
string name;
int age;

public PersonEventArgs() { }
public PersonEventArgs(PersonEventArgs person) {
this.name = person.name;
this.age = person.age;
}
public PersonEventArgs(string name,int age) {
this.name = name;
this.age = age;
}
public override string ToString()
{
return string.Format("name is {0},age is {1}!",name,age);
}
}

//声明一个添加人员的委任
delegate void AddPersonEventHandle(object sender,PersonEventArgs args);
class AddPersonListener
{
//在委托的机制下我们建立一个添加事件
public event AddPersonEventHandle addPerson;

ArrayList personList = new ArrayList();

/// <summary>
/// 当我们向列表中添加一个对象时就触发该事件
/// </summary>
/// <param name="person"></param>
public void AddPerson(PersonEventArgs person) {

personList.Add(person);
//多路广播
addPerson += new AddPersonEventHandle(AddPersonListener_addpersonEvent);
//检测到监听的事件
OnAdd(person);
}
//具体委托的方法
void AddPersonListener_addpersonEvent(object sender, PersonEventArgs args)
{
Console.WriteLine(args.ToString());
}
//声明一个可以被重写的OnAdd的保护函数
public virtual void OnAdd(PersonEventArgs args) {
if (addPerson != null) {
addPerson(this, args);
}
}
}

class Program
{
static void Main(string[] args)
{
AddPersonListener listener = new AddPersonListener();
PersonEventArgs person = new PersonEventArgs("Joea");

listener.AddPerson(person);
}
}


上面的代码是实现一个我们向personList中添加一个对象时就把对象中的name打印出来。在其中我们定义个一个事件addPerson,关键字是event。在我们使用事件的时候,必须要声明对应的委托,而触发事件,其实就是在使用委托链。

最后我们有必要搞懂.Net Framework的编码规范:

委托类型的名称都应该以 EventHandler结束。

委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。

事件的命名为 委托去掉 EventHandler之后剩余的部分。

继承自EventArgs的类型应该以EventArgs结尾。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: