• 委托与事件


    委托:譬如别人委托你买你去书挑选一本好的c#的书,而你却因为懒得动,直接去了dearbook选书,然后送上门。然后你转交给了朋友。这就是现实中的委托。-------你的好朋友并不知道,你没有去书店选。(不关注方法的细节)
    c#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。委托代表了方法。
    为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确

     2using System;
     3
     4namespace test1
     5{
     6 /// <summary>
     7 /// Class1 的摘要说明。
     8 /// </summary>

     9 
    10 class MathsOperations
    11 {
    12  public static double multiplyByTwo(double value)
    13  {
    14   return value*2;
    15  }

    16
    17  public static double Square(double value)
    18  {
    19   return value*value;
    20  }

    21 }

    22
    23 delegate double DoubleOp(double x);
    24
    25 class test1
    26 {
    27  static void Main()
    28  {
    29   DoubleOp[] operations =
    30    {
    31     new DoubleOp(MathsOperations.multiplyByTwo),
    32     new DoubleOp(MathsOperations.Square)
    33    }
    ;
    34
    35   for(int i=0;i<operations.Length;i++)
    36   {
    37    Console.WriteLine("Using operations[{0}];",i);
    38    ProcessAndDisplayNumber(operations[i],2.0);
    39    ProcessAndDisplayNumber(operations[i],5);
    40    Console.WriteLine();
    41   }

    42  }

    43
    44  static void ProcessAndDisplayNumber(DoubleOp action,double value)
    45  {
    46   double result = action(value);
    47   Console.WriteLine("Value is {0},result of operation is {1}",value,result);
    48  }

    49 }

    50 
    51
    52}

    有些时候不用委托是很难实现某些功能的
     1    class BubbleSorter
     2    {
     3        static public void Sort(object[] sortArray,CompareOp gtMethod)
     4        {
     5            for(int i=0;i<sortArray.Length;i++)
     6            {
     7                for(int j=i+i;i<sortArray.Length;j++)
     8                {
     9                    if(gtMethod(sortArray[j],sortArray[i]))
    10                    {
    11                        object temp = sortArray[i];
    12                        sortArray[i] = sortArray[j];
    13                        sortArray[j] = temp;
    14                    }

    15                }

    16            }

    17        }

    18    }

    19
    20    delegate bool CompareOp(object lhs,object rhs);
    21
    22    class Employee
    23    {
    24        private string name;
    25        private decimal salary;
    26
    27        public Employee(string name,decimal salary)
    28        {
    29            this.name=name;
    30            this.salary=salary;
    31        }

    32        public override string ToString()
    33        {
    34            return string.Format(name + ",{0:c}",salary);
    35        }

    36        public static bool RhslsGreater(object lhs,object rhs)
    37        {
    38            Employee empLhs = (Employee)lhs;
    39            Employee empRhs = (Employee)rhs;
    40            return(empLhs.salary>empRhs.salary)?true:false;
    41        }

    42    }

    43
    44
    45    class test1
    46    {
    47        static void Main()
    48        {
    49            Employee [] employees = 
    50            {
    51                new Employee("abc",100),
    52                new Employee("bbc",122),
    53                new Employee("bb",111),
    54            }
    ;
    55
    56
    57            CompareOp employeeCompareOp = new CompareOp(Employee.RhslsGreater);
    58            BubbleSorter.Sort(employees,employeeCompareOp);
    59
    60            for(int i=0;i<employees.Length;i++)
    61            {
    62                Console.WriteLine(employees[i].ToString());
    63            }

    64        }

    65    }

    66}
    多播委托:委托包含多个方法。按顺序连续调用多个方法,委托的签名必须返回void(否则,返回值应送到何处)。实际上,如果编译器发现某个委托返回void,就会自动假定这是一个多播委托
    例子:
     1using System;
     2
     3namespace test1
     4{
     5    /// <summary>
     6    /// Class1 的摘要说明。
     7    ///</summary>

     8    
     9        class MathsOperations
    10        {
    11            public static void multiplyByTwo(double value)
    12            {
    13                double result = value*2;
    14                Console.WriteLine(
    15                    "Multiplying by 2:{0} gives {1}",value,result);
    16            }

    17    
    18            public static void Square(double value)
    19            {
    20                double result = value*value;
    21                Console.WriteLine(
    22                    "Squareing:{0} gives {1}",value,result);
    23            }
        
    24        }

    25    
    26        delegate void DoubleOp(double value);
    27    
    28        class test1
    29        {
    30            static void Main()
    31            {
    32                 //或,委托可以识别 +,+=,-,-=
    33                //DoubleOp operations = new DoubleOp(MathsOperations.multiplyByTwo);
    34                //operations += new DoubleOp(MathsOperations.Square);
    35
    36                DoubleOp opertaion1 = new DoubleOp(MathsOperations.multiplyByTwo);
    37                DoubleOp operation2 = new DoubleOp(MathsOperations.Square);
    38                DoubleOp operations = opertaion1 + operation2;
    39
    40                ProcessAndDisplayNumber(operations,2.0);
    41                ProcessAndDisplayNumber(operations,40.0);
    42            }

    43    
    44            static void ProcessAndDisplayNumber(DoubleOp action,double value)
    45            {
    46                Console.WriteLine("\nProcessAndDisplay Number called with value = " +
    47                    value);
    48                action(value);
    49            }

    50        }

    51}

    事件:事件与委托是密不可分的。
    应用程序是通过windows来通信的,而windows又是使用预定义的消息与应用程序通信的。微软已经定义好了N多个系统事件(消息),譬如点击一个摁钮,打开一个下拉框,等等。事件接收器就是指发生某事件时被通知的任何应用程序,对象或组件。事件发送器可以是应用程序的一个对象或程序集。系统事件中如鼠标单击,键盘按键。.net程序中的事件发送器就是.net的运行库,.net framework把windows消息封装在了事件中,偶没学过windows编程,对windows消息的机制不甚了解。大概就是button的click事件封装了windows的WM_MOUSECLICK消息。然后就可以直接调用click事件了。
    button1.click  += new EventHandler(Button_Click);
    事件              +=    实例化一个委托(某个方法)   //可多个方法依次添加到委托列表,但不能保证调用时方法的顺序。
    EventHandler 委托在Farmework是已定义的,位于System命名空间,在所有的Farmework中的定义的事件都是用它。添加到该委托列表的方法都必须有相同的签名。private void Button_Click(object sender , Eventargs e) //1参:引发事件的对象,2参:包含有关事件的其他有用信息的对象,可任意类型,只要派生于它均可,譬如MouseDownEventArgs 类型。

    委托和事件在用户界面程序里用的比较的多,比如象在winformwebform的用户UI上的button和它的click事件:

    // Button1_Click()方法绑定到按钮控件Button1Click事件上

    this.Button1.Click += new System.EventHandler(this. Button1_Click);

    private void Button1_Click(object sender, System.EventArgs e)    // Button1_Click()方法

    {

                    …… 

    }

    然而除了用户界面程序外,在很多其他地方也用到了事件驱动模式,比如观察者模式(Observer)或发布/订阅(Publish/Subscribe)里:在一个类里发布(Publish)某个可以被触发的事件,而其他的类就可以来订阅(Subscribe)该事件。一旦这个发布者类触发了该事件,那么运行时环境会立刻告知所有订阅了该事件的订阅者类:这个事件发生了!从而各个订阅者类可以作出它们自己的反应(调用相应方法)。


  • 相关阅读:
    UILabel 设置字体间的距离 和 行与行间的距离
    IB_DESIGNABLE 和 IBInspectable 的使用
    干货博客
    GitHub克隆速度太慢解决方案
    实时(RTC)时钟,系统时钟和CPU时钟
    折腾了好久的vscode配置c/c++语言环境(Windows环境下)
    c语言中的malloc函数
    记录一下关于在工具类中更新UI使用RunOnUiThread犯的极其愚蠢的错误
    记录关于Android多线程的一个坑
    Android中限制输入框最大输入长度
  • 原文地址:https://www.cnblogs.com/huoxingren/p/635270.html
Copyright © 2020-2023  润新知