委托和事件
- 委托
- 声明
- 实例化
- 调用
- 将类型安全的函数指针(方法)作为其他方法的参数进行传递,从而实现函数回调方法
- 委托:匿名方法委托
- 多播委托
-
- 事件
- 事件实际上是委托的一种特殊形式,C#使用一种委托模型来实现事件
- 事件的声明、订阅和取消
- 事件:实现的步骤
委托
-
委托是C#用来处理需用函数指针来处理的情况的
-
委托是完全面向对象的(同时封装了对象实例和方法),是类型安全的
-
委托可保存对方法的引用的类,但只能对于其签名匹配的方法进行引用
-
委托声明定义一个从 System.Delegate 类派生的类
-
委托实例封装了一个调用列表,该列表列出了一个或多个方法,每个方法称为一个可调用实体
-
对于实例方法,可调用实体由该方法和一个相关联的实例组成
声明
[委托修饰符] delegate 返回值类型 委托名 ([形参列表]);
实例化
委托名 委托实例名 = new 委托名(匹配方法);
调用
委托实例名(实参列表);
将类型安全的函数指针(方法)作为其他方法的参数进行传递,从而实现函数回调方法
delegate void D(int x);
class C
{
public static void M1(int i){Console.WriteLine("C.M1:" + i);}
public static void M2(int i){Console.WriteLine("C.M2:" + i);}
public void M3(int i){Console.WriteLine("C.M3:" + i);}
}
class Test
{
static void Main()
{
D d1 = new D(C.M1);
d1(-1);
D d2 = C.M2;
d2(-2);
C objc = new C();
D d3 = new D(objc.M3);
d2(-3);
Console.ReadKey();
}
}
委托:匿名方法委托
- 无需先声明类或结构以及与委托匹配的方法,而是在创建委托的实例时,直接声明与委托匹配的方法的代码块(匿名方法)
delegate void Printer(string s);
class TestClass
{
static void Main()
{
Printer p = delegate(string j)
{ Console.WriteLine(j); };
p("使用匿名方法的委托的调用。");
Console.ReadKey();
}
}
多播委托
委托也可以包含多个方法,这种委托称为多播委托
- 调用多播委托实例,则按顺序依次调用多播委托实例封装的调用列表中的多个方法
- 声明多播委托时,其返回类型必须为void
- 三个静态方法:Combine, Remove, RemoveAll
- 多播委托通过 + 或 += 向多播委托实例封装的调用列表中添加方法;通过 – 或 – = 从多播委托实例封装的调用列表中删除方法
delegate void D(int x);
class C
{
public static void M1(int i) { Console.WriteLine("C.M1: " + i);}
public static void M2(int i) { Console.WriteLine("C.M2: " + i);}
}
class Test
{
static void Main()
{ D cd1 = new D(C.M1); cd1(-1);
D cd2 = new D(C.M2); cd2(-2);
D cd3 = cd1 + cd2; cd3(10);
cd3 -= cd1; cd3(20);
cd3 -= cd2;
cd3 -= cd1;
Console.ReadKey();
}
}
委托:委托的异步调用
![在这里插入图片描述](https://img-blog.csdnimg.cn/614f8d4993814e639ae86c0b75770ef0.png)
委托:委托的兼容性
-
与委托向对应的方法不必与委托签名完全匹配
-
方法M与委托类型D兼容条件:
-
D和M的参数数目相同,且各自对应参数具有相同的ref或out修饰符
-
对于每个ref或out参数,D中的参数类型与M中的参数类型相同
-
存在从M的返回类型到D的返回类型的标识或隐式引用转换。即允许方法具有的派生返回类型比委托中定义的更多(协变)
-
每一个值参数(没有 ref 或 out 修饰符的参数)都存在从D中的参数类型到M中的对应参数类型的标识或隐式引用转换。允许方法具有的派生参数类型比委托类型中的更少(逆变)
事件
处理机制;事件的声明、订阅和取消;.NET Framework事件模型
-
一种使对象或类能够提供通知的成员
-
类或对象可以通过事件向其他类或对象通知发生的相关事情
-
发送(或引发)事件的类称为“发行者”(生产者),接收(或处理)事件的类称为“订户”(消费者)
-
事件是对象发送的消息,以发信号通知操作的发生
-
在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的
事件实际上是委托的一种特殊形式,C#使用一种委托模型来实现事件
-
事件模型分为事件生产者和事件消费者,其处理机制大致可以分为下列4步:
-
在事件生产者类中声明一个事件成员,即某种事件处理委托(简称为事件委托)的实例(多播事件委托实例);
-
在事件消费者类中声明与事件委托相匹配的事件处理方法;
-
通过“+=”向多播事件委托实例封装的调用列表中添加事件处理方法,或通过“-=”从多播事件委托实例封装的调用列表中删除事件处理方法;
-
在事件生产者类中添加有关发生事件的代码,即当满足某种条件时(发生事件),则调用委托,即调用多播事件委托实例封装的调用列表中添加的事件处理方法。如果没有订阅,即事件实例为Null,则不作任何处理
![在这里插入图片描述](https://img-blog.csdnimg.cn/d775441a96e043a0b18560bf387b97c3.png)
button.Click += new EventHandler(this.Button_Click);
private void Button_Click(object sender, EventArgs e)
{
box.BackColor = System.Drawing.Color.Green;
}
事件的声明、订阅和取消
public delegate void SampleEventHandler(object sender, EventArgs e);
public class Publisher
{
public event SampleEventHandler SampleEvent;
protected virtual void RaiseSampleEvent()
{
SampleEvent(this, new EventArgs());
}
}
public class Subscriber
{
public static void Method1(object sender, EventArgs e)
{
Console.WriteLine("To Do Something...");
}
public static void Method2(object sender, EventArgs e)
{
Console.WriteLine("To Do Something...");
}
}
public static void Main()
{ / /创建委托实例
SampleEventHandler d1 = new SampleEventHandler(Subscriber.Method1);
Publisher p = new Publisher();
p.SampleEvent += d1;
p.SampleEvent += new SampleEventHandler(Subscriber.Method2);
p.SampleEvent -= d1;
Console.ReadKey();
}
事件:实现的步骤
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)