zoukankan      html  css  js  c++  java
  • (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

  • 相关阅读:
    添加远程库
    Git远程仓库
    Git 删除文件
    Git撤销暂存区stage中的内容
    Git 暂存区的概念
    Git add和commit步骤分析
    2017CCPC秦皇岛 E题String of CCPC&&ZOJ3985【模拟】
    2017CCPC秦皇岛 C题Crusaders Quest&&ZOJ3983【模拟+STL】
    2017CCPC秦皇岛 L题One-Dimensional Maze&&ZOJ3992【模拟】
    HDU2444 The Accomodation of Students【匈牙利算法】
  • 原文地址:https://www.cnblogs.com/fdyang/p/2909610.html
Copyright © 2011-2022 走看看