委托与事件

本篇内容是阅读《深入理解C#》和《C#与.net4高级程序设计》的笔记,关注于委托这一部分。

1. 委托是用来干什么的

委托相当于一个对方法(method)的接口,它提出有这样一种方法:已经知晓了它们的名称和类型,即已经声明了,但是这个方法要怎样具体实施以达成目的还不清楚,需要在另外的地方给出具体的代码。
委托是对一类方法的抽象,要执行具体的工作需要调用具体的委托实例。就像类(class)是对一类事物的抽象,真正在实际中使用的是具体的对象(object)。
委托的好处是提供了一个更工程化的思路:当我知道需要这样一个方法时,我只考虑它的效果,而把具体应该怎样做这个问题留给真正执行这些操作的人来考虑。一方面,我不知道具体执行时候的情况是怎样的,给出细节的代码很困难;另一方面,把事情的结果和过程分隔开也提高了考虑事情的效率。
本质上,委托是一个类型安全的对象,它指向程序中另一个(或多个)以后会被调用的方法。

2. 使用委托的4个步骤

a. 声明委托类型(delegate type)

规定参数类型列表和返回类型,如:

    delegate void StringProcessor(string input);

b. 要执行的代码,必须有某个方法告知了这个委托到底要做什么

首先为委托实例执行时使用的方法(代码)起一个名字,叫“委托实例的操作”(the action of the delegate instance)。这里所讨论等东西没有官方叫法,这个名字是《C# in Depth》作者Jon Skeet自己起的,中文参考中文版的翻译。
可能提供“委托实例的操作”的方法满足下面两个特点(称为有同样的签名(signature)):
- 参数列表和委托类型所声明的相同,即有相同的数量,且对应参数是同一个类型。
- 返回值的类型相同。
比如(针对前面的例子)

    void PrintString(string x)

c. 创建委托实例(delegate instance)

  • 如果委托实例和“委托实例的操作”在一个类(class)中
    StringProcessor proc = new StringProcessor(PrintString);
  • 不在一个类中时,需要限定“委托实例等操作”是定义在哪个类里的
    i. 如果操作是静态的,比如PrintString是StatisticMethods类中的一个方法:
    StringProcessor proc1 = new StringProcessor(StatisticMethod.PrintString);
   ii. 如果操作是实例方法,比如PrintString是InstanceMethods类中的一个实例方法:
InstanceMethods instance = new InstanceMethods;
StringProcessor proc2 = new StringProcessor(instance.PrintString);

d. 调用(invoke)委托实例

delegate类中提供了用于调用委托实例的方法:Invoke。这个方法和所声明的委托类型使用相同的参数列表和返回类型。
在C#中,delegate类的表达式(通常就是这个变量或实例)可以为视为一个方法,也就是说proc1(“Hello”)和proc1.Invoke(“Hello”)的效果是一样的,实际上,前者会被编译成后者。

3. 一个简单的例子

   using System;

   delegate void StringProcessor(string input); // 声明委托类型

   class Person
   {
       string name;
       public Person(string name) { this.name = name; }
       public void Say(string message) // 委托实例的操作
       {
           Console.WriteLine("{0} says: {1}", name, message);
       }
   }
   class Background
   {
       public static void Note(string note) // 委托实例的操作
       {
           Console.WriteLine("({0})", note);
       }
   }

   class SimpleDelegateUse
   {
       static void Main()
       {
           Person jon = new Person("Jon");
           Person tom = new Person("Tom");

           // 创建委托实例
           StringProcessor jonsVoice, tomsVoice, background; 
           jonsVoice = new StringProcessor(jon.say);
           tomsVoice = new StringProcessor(tom.say);
           background = new StringProcessor(Background.Note);

           // 调用委托实例
           jonsVoice("Hello, son.");
           tomsVoice("Hello, Daddy!");
           background("An airplane flies past.");
       }
   }

4. 当我们使用委托时,程序究竟做了什么

.net中的System.Delegate和System.MulticastDelegate构建了委托这个概念。使用Delegate关键字创建委托时,间接(自动地)声明了一个派生自System.MulticastDelegate的类。(System.MulticastDelegate是System.Delegate的子类。)
比如,关于委托的调用,定义委托类型时会生成一个密封类,其中有3个编译器生成的方法,这个3个方法的参数和返回值基于委托的声明。下面的伪码说明了这个模式:

     public sealed class DelegateName : System.MulticastDelegate
       {
           public delegateReturnValue Invoke(allDelegateInputRefAndOutParams);

           
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值