委托与事件的入门说明

来源:互联网 发布:商业数据分析师的能力 编辑:程序博客网 时间:2024/05/16 07:23

委托的声明

public delegate void MyDelegate(string str);

1.委托的定义和方法的定义类似,只是在前面加了一个delegate,但委托不是方法,它是一种类型。是一种特殊的类型,看成是一种新的对象类型比较好理解。用于对与该委托有相
同签名的方法调用。

2.委托相当于C++中的函数指针,但它是类型安全的。

3.委托是从System.Delegate派生,但不能象定义常规类型一样直接从System.Delegate派生,对委托的声明只能通过上面的声明格式进行定义。关键字delegate通知编译器这是一个委托类型,从而在编译的时候对该类进行封装,对这一过程C#定义了专门的语法来处理这一过程。

4.不能从一个委托类型进行派生,因为它也是默认sealed的

5.委托即可以对静态方法进行调用也可以对实例方法进行调用。

6.每个委托类型包含一个自己的调用列表,当组合一个委托或从一个委托中删除一个委托时都将产生个新的调用列表。

7.两个不同类型的委托即使它们有相同的签名和返回值,但还是两个不同类型的委托。但其实在使用中可看作是相同的。


委托的比较

C#中对委托定义了两个操作符 == 和 !=
在以下情况下两个委托是相等的:
1.当两个委托都同时为null的时候
2.当两个委托都不为null时,下列情况下是相等的。
a.当两个委托的各自的调用列表只含有一个入口点的时候
在下列情况下是相等的
(1) 调用同一对象的同一静态方法
(2) 调用同一对象的同一实例方法
b.当两个委托具有多个入口点时
在下列情况下是相等的
(1)只有当它们调用列表中的调用的方法按顺序都一一对应相同的对象及对象的同一方法的时候

如上所述的两个不同类型的委托但是它们具有相同的签名和返回值时,只要满足上述条件的,即使它们类型
不同,但比较的结果也是相同的。

委托的异常处理

当调用该委托的方法中发生了异常时,首先在调用该委托的方法中搜寻catch语句块。如果没有,则去该委托调用的方法中去寻找有没有catch语句块,这和调用方法发生异常的处理是一样的。

当调用一个为null的委托即委托中列表中不存在调用方法时,将发生NullRefrenceException委托的注意点:
当一个委托有多个入口点的时候,调用委托将依该委托的调用列表中的方法的顺序依次调用.这些方法共享一个参数集合,所以当委托有返回值的时候调用完这个委托后的返回值是最后一个方法的返回值或是有out参数.如果该委托的参数为ref(引用类型),那么在招待第一个方法的时候如果对这个参数的值有所改变,那么这个改变将会影响到后面的方法调用.

委托的一个例子

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// 创建一个委托实例,封装C类的静态方法M1
MyDelegate d1 = new MyDelegate(C.M1);
d1("D1"); // M1

// 创建一个委托实例,封装C类的静态方法M2
MyDelegate d2 = new MyDelegate(C.M2);
d2("D2"); // M2

// 创建一个委托实例,封装C类的实例方法M3
MyDelegate d3 = new MyDelegate(new C().M3);
d3("D3"); // M3

// 从一个委托d3创建一个委托实例
MyDelegate d4 = new MyDelegate(d3);
d4("D4"); // M3

// 组合两个委托
MyDelegate d5 = d1 + d2;
d5 += d3;
d5("D5"); // M1,M2,M3

// 从组合委托中删除d3
MyDelegate d6 = d5 - d3;
d6("D6"); // M1,M2
d6 -= d3; // 虽然d6调用列表中已经没有d3了,但这样只是不可能的移除没有错误发生
d6("D6"); // M1,M2
d6 -= d6;
//d6("D6"); 此时d6的调用列表为空,d6为null,所以引发System.NullReferenceException


MyDelegate d7 = new MyDelegate(C1.P1);
d7("D7"); // C1.P1

MyDelegate d8 = new MyDelegate(new C2().P1);
d8("D8"); // C2.P1

}
}

// 声明一个委托MyDelegate
public delegate void MyDelegate(string str);

public class C
{
public static void M1(string str)
{
Console.WriteLine("From:C.M1: ", str);
}

public static void M2(string str)
{
Console.WriteLine("From:C.M2: ", str);
}

public void M3(string str)
{
Console.WriteLine("From:C.M3: ", str);
}
}

public class C1
{
public static void P1(string str)
{
Console.WriteLine("From:C1.P1: ", str);
}
}

public class C2
{
public void P1(string str)
{
Console.WriteLine("From:C2.P1: ", str);
}
}
}

事件委托

事件概述

事件就是当对象或类状态发生改变时,对象或类发出的信息或通知。发出信息的对象或类称为"事件源",对事
件进行处理的方法称为"接收者",通常事件源在发出状态改变信息时,它

并不知道由哪个事件接收者来处理.这就需要一种管理机制来协调事件源和接收者,C++中通过函数指针来完成的.在C#中事件使用委托来为触发时将调用的方法提供类型安全的封装


事件的声明

1.声明一个委托
public delegate void EventHandler(object sender, System.EventArgs e);

2.声明一个事件
public event EventHandler Changed;

3.引发一个事件
public OnChanged(EnventArgs e)
{
if ( Changed != null)
{
Changed(this,e);
}
}

4.定义事件处理程序
public MyText_OnChanged(Object sender,EventArgs e)

5.订阅事件(将事件处理程序添加到事件的调用列表中)

myText.Changed += EventHandler(MyText_OnChanged);

下面的一个小例子说明了怎样定义一个完整的事件机制:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyText myText = new MyText();

// 将事件处理程序添加到事件的调用列表中(即事件布线)
myText.Changed += new MyText.ChangedEventHandler(myText_Changed);

string str = "";
while (str != "quit")
{
Console.WriteLine("please enter a string:");
str = Console.ReadLine();
myText.Text = str;
}
}

// 对Change事件处理的程序
private static void myText_Changed(object sender, EventArgs e)
{
Console.WriteLine("text has been changed :n" ,((MyText)sender).Text);
}
}
public class MyText
{
private string _text = "";

// 定义事件的委托
public delegate void ChangedEventHandler(object sender, EventArgs e);

// 定义一个事件
public event ChangedEventHandler Changed;
// 用以触发Change事件
protected virtual void OnChanged(EventArgs e)
{
if (this.Changed != null)
this.Changed(this, e);
}

// Text属性
public string Text
{
set
{
this._text = value;
// 文本改变时触发Change事件
this.OnChanged(new EventArgs());
}
}
}
}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电池充不进去电怎么办 电脑充不进去电怎么办 苹果5c白苹果怎么办 港行不支持电信卡怎么办 安卓导航不开机怎么办 鞭炮放一半不响怎么办 禁止鸣笛的地方鸣笛了怎么办 手被炮仗炸了怎么办 手被猴子抓伤了怎么办 炸东西剩的油怎么办 炸臭豆腐剩的油怎么办 油炸久了油发黑怎么办 炸鱼的时候粘锅怎么办 吃了葱蒜有味怎么办 哺乳期喝了抹茶怎么办 干炸小黄鱼凉了怎么办 烧鱼酱油放多了怎么办 夏天腿干燥起皮怎么办 螃蟹柿子同时吃了怎么办 柿子和螃蟹一起吃怎么办 螃蟹和柿子吃了怎么办 今天为什么很多网站打不开怎么办 网上报名人太多服务器卡怎么办 网站换了电脑打不开怎么办 感冒时后背发凉怎么办? 脚扭了脚背疼怎么办 五妙水仙膏干了怎么办 红苹果接不到任务了怎么办 我判刑了家里老母亲怎么办 离婚之前对方把财产转移怎么办 有人侵犯我的名誉权怎么办 耳朵被咬红肿了怎么办 孕29周呼吸困难怎么办 痔疮出血一个星期了怎么办 怀孕长了副乳该怎么办 备孕期间长痔疮怎么办 15年凌度智能钥匙全丢怎么办 西水开发商跑了怎么办 如果房子烂尾了怎么办 小斗鱼出生后喂年丰虾在缸底怎么办 脸上痘痘红肿痒怎么办