(C#)中断程序流程,处理事件(委托,事件,Lambda表达式)-1/3

事件和委托的用途在于实现Runtime的两种机制: 1)事件通知  2)事件处理

委托(delegate)是指向一个方法的指针,通过制定一个委托名称,来调用方法。可以动态的更改一个委托引用的方法。

(委托类型用来响应应用程序中的回调(callback), 委托和C++的函数指针相似,但是委托是类型安全的。)

 委托类型包括3个重要的信息:

  • 它所调用的方法的名称
  • 该方法的参数(可选)
  • 该方法的返回值(可选)

.NET委托既可以指向静态方法,也可以指向实例方法。并且可以在运行时动态调用其指向的方法。

.NET的每一个委托都被自动赋予了同步或异步访问方法的能力,可以不用创建而后管理Thread对象而直接调用辅助线程上的方法。

定义委托类型

//此委托可以指向任何传入两个整数,返回的一个整数的方法。
//为了便于理解,在原理上等同于C/C++, typedef int (*BinaryOperation)(int x, int y), 在这里 BinaryOperation 就是函数指针类型,此函数返回int值 public delegate int BinaryOperation(int x, int y);

当编译器处理委托类型时,先自动产生一个派生自System.MulticastDelegate的密封类,并定义了3个public方法

  • Invoke()为核心方法,用来以同步方式调用委托对象维护的每个方法。
  • BeginInvoke()和EndInvoke()在第二个执行线程上异步调用当前方法。

创建一个类SimpleMath,包含方法(加,减法)。完全匹配上述委托的调用机制(传入两个int参数,返回1个int参数).

        public class SimpleMath
        {
            public static int Add(int x, int y)
            {
                return x + y;
            }
            public static int Subtract(int x, int y)
            {
                return x - y;
            }
        }

创建委托对象,调用方法。

            // 创建一个 BinaryOperation 对象,并指向 SimpleMath.Add()静态方法。
       // C/C++: BinaryOperation bo = SimpleMath.Add; int result = bo(111, 222);
BinaryOperation bo = new BinaryOperation(SimpleMath.Add); // 使用委托对象调用 SimpleMath.Add()方法。 Console.WriteLine("111 + 222 = {0}", bo(111,222));

在底层,运行库实际上在MulticastDelegate派生类上隐式调用了编译器生成的Invoke()方法。实际上也可以显式调用Invoke()方法。

            // 显式调用 SimpleMath.Add()方法。
            Console.WriteLine("111 + 222 = {0}", bo.Invoke(111,222)); 

.NET是类型安全的,如果试图将一个不匹配的方法(例如输入一个int参数)传入委托,将会收到编译器错误。

.NET支持多路广播,即一个委托对象可以维护一个可调用方法的列表。给一个委托对象添加多个方法时,不用直接分配,重载+=操作符即可。

bo += SimpleMath.Subtract;

从委托的调用列表中移除成员方法的时候的时候,用Remove()方法,或者用-=操作符。

 所有代码如下:

namespace ConsoleApplication1
{
    class Program
    {
        public delegate int BinaryOperation(int x, int y);

        public class SimpleMath
        {
            public static int Add(int x, int y)
            {
                Console.WriteLine("Method Add is invoked.");
                return x + y;
            }
            public static int Subtract(int x, int y)
            {
                Console.WriteLine("Method Subtract is invoked.");
                return x - y;
            }
        }
                
    
        static void Main(string[] args)
        {
            // 创建一个 BinaryOperation 对象,并指向 SimpleMath.Add()方法。
            BinaryOperation bo = new BinaryOperation(SimpleMath.Add);

            // 使用委托对象调用 SimpleMath.Add()方法。
            Console.WriteLine("111 + 222 = {0}", bo(111,222));

            // 增加方法列表
            bo += SimpleMath.Subtract;
            Console.WriteLine("Final result is: {0}", bo(111, 222)); 

            Console.ReadLine();
        }
    }
}

输出结果:

Method Add is invoked.

111 + 222 = 333

Method Add is invoked.

Method Subtract is invoked.

Final result is: -111

在C/C++ 中的函数指针更容易理解 delegate. 上面的例子等同如下:

head 文件,定一了一个函数指针,和一个类。

typedef int (*BinaryOperation)(int x, int y); 

class SimpleMath
{
public:
    static int Add(int x, int y); 
    static int SubStract(int x, int y); 
}; 

cpp文件

int _tmain(int argc, _TCHAR* argv[])
{
    BinaryOperation bo = SimpleMath::Add;  

    int result = bo(12, 23); 

    printf("%d\n", result); 
    return 0;
}

int SimpleMath::Add(int a, int b)
{
    return a+b; 
}

int SimpleMath::SubStract(int a, int b)
{
    return a-b; 
}

 

=================================================

再举个例子理解一下“委托”。

委托就是请人办事。

譬如A项目组有项目经理,软件Lead,软件工程师,测试工程师等组成。软件组会做很多工作,通常都是软件Lead分配的。但是软件Lead本人是不亲自做事的。他是对外部的窗口。比如他手下有两个牛X的工程师,一个叫Bill,一个叫Steven。活儿都是他俩干的。

也就是说,所有的工作,都是软件Lead“委托”Bill, 和 Steven来做的。

        static void Main(string[] args)
        {
            SoftwareLead fred = new SoftwareLead();

            fred.doWork(); 
        }
    public class SoftwareLead
    {
        public delegate void AssignSoftwareWork(); 

        private SoftwareEngineer bill = new SoftwareEngineer("Bill");

        private SoftwareEngineer steven = new SoftwareEngineer("Steven"); 

        public void doWork()
        {
            AssignSoftwareWork doWork = new AssignSoftwareWork(bill.UpdateFirmware);
            doWork(); 
        }
    }
    public class SoftwareEngineer
    {
        private string engineerName;

        public SoftwareEngineer(string name)
        {
            this.engineerName = name; 
        }

        public void UpdateFirmware()
        {
            Console.WriteLine("{0} is updating firmware...", this.engineerName); 
        }

        public void FixBugs()
        {
            Console.WriteLine("{0} is fixing bugs...", this.engineerName); 
        }
    }

委托当然可以请“多人”办事。也就是说可以给委托增加更多的方法。/* 指针函数列表*/

比如这次的软件组的工作是让Bill升级FW,然后让Bill再fix一些bug,同时也会安排steven来fix一些bug。

        public void doWork()
        {
            AssignSoftwareWork doWork = new AssignSoftwareWork(bill.UpdateFirmware);
            doWork += new AssignSoftwareWork(bill.FixBugs);
            doWork += new AssignSoftwareWork(steven.FixBugs); 
            doWork(); 
        }

输出:

Bill is updating firmware...
Bill is fixing bugs...
Steven is fixing bugs...

 

显然,上述的code还是有些问题的,Software Lead的code过于繁琐,并且,私自的把另外两个小弟做成了软件Lead类的字段。

再使用泛型委托Action 和 Lambda表达式后,如下代码更贴近现实生活。

SoftwareLead类 喊出一句话后,就assign工作。(更加通用了。)。

    public class SoftwareLead
    {
        public void doWork(Action assignWork)
        {
            Console.WriteLine("Hey buddies, let's start working...");
            assignWork(); 
        }
    }

具体的工作呢,在SoftwareLead 的一个对象里才会说明。

        static void Main(string[] args)
        {
            SoftwareLead fred = new SoftwareLead();
            SoftwareEngineer bill = new SoftwareEngineer("Bill"); 
            SoftwareEngineer steven = new SoftwareEngineer("Steven");

            fred.doWork(() =>
                {
                    bill.UpdateFirmware();
                    steven.FixBugs(); 
                }); 
        }

 

参考:

http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html

 

 

 

转载于:https://www.cnblogs.com/fdyang/archive/2013/02/09/2909610.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值