zoukankan      html  css  js  c++  java
  • 再探委托与事件


    委托

    在这里补充两个对委托运用得比较少的示例:

    一、将委托作为参数传递,然后再调用;

    二、使用委托调用内部类中的方法;

    示例一:委托作为参数

    委托作为参数.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace 委托作为参数
    {
        
    class 计算器
        {
            
    public delegate int delCalculate(int a, int b);

            
    // 将委托作为参数
            public void Fun(int a, int b, delCalculate cal)
            {
                
    if (cal != null)
                {
                    Console.WriteLine(cal(a,b));
                }
            }

            
    // 加法
            public int Add(int a, int b)
            {
                
    return a + b;
            }
            
    // 减法
            public int Reduce(int a, int b)
            {
                
    return a - b;
            }
        }

        
    class Run
        {
            
    static void Main(string[] args)
            {
                计算器 js 
    = new 计算器();

                
    //调用加法
                计算器.delCalculate d1 = new 计算器.delCalculate(js.Add);
                js.Fun(
    20,10, d1); //将委托作为参数

                
    //调用减法
                js.Fun(20,10,new 计算器.delCalculate(js.Reduce));
            }
        }
    }


    示例二:委托调用内部类的方法

    委托调用内部类的方法.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace 委托调用内部类的方法
    {
        
    class Person
        {
            
    public delegate void myDelegate(string str);

            
    public void Fun(string str)
            {
                Console.WriteLine(str);
            }

            
    //内部类的调用
            public class InnerClass
            {
                
    public void SubFun(string str)
                {
                    Console.WriteLine(str);
                }
            }
        }

        
    class Program
        {
            
    static void Main(string[] args)
            {
                Person p 
    = new Person();
                
    //内部委托的实例化(用类名调用)
                Person.myDelegate pm1 = new Person.myDelegate(p.Fun);
                pm1(
    "内部委托调用的方法");

                
    //内部类 InnerClass
                Person.InnerClass pc = new Person.InnerClass();
                Person.myDelegate pm2 
    = new Person.myDelegate(pc.SubFun);
                pm2(
    "内部委托调用内部类的方法");
            }
        }
    }


    事件

    由于MSDN含混不清的误导,很多人会认为:事件就是一种受限的委托。但实际上不是!
    事件与委托的关系好比字段与属性的关系。
    事件实际上是一种委托属性,只不过这个属性重载的不是赋值运算符,而是+=和-=运算符。

    对于一个属性而言,对它的赋值和取值运算会被转换为两个方法的调用。
    例如:obj.A 这个属性
    obj.A = "aaa";       将调用 set 访问器:   set {  _a = value;  }
    string a = obj.A;   将调用 get 访问器:   get {  return _a;  }

    而事件也是一样,假设有一个事件obj.E,则下面的表达式也等同于后面的形式:
    obj.E += d;              obj.add_E( d )
    obj.E -= d;              obj.remove_E( d )


    事件与属性的共同点:
    事件也可以被继承;
    事件也可以被重写;
    事件也可以是虚的或者抽象的(表现在add和remove方法是抽象的或者虚的);

    理论上,事件的add和remove方法也可以有不同的访问权限。


    事件与属性的不同点:
    属性是必须实现的,事件则不必(或者说,事件是最早出现的自动属性);

    与自动属性一样,事件也会创建一个字段来保存对应的委托实例,而这个字段与事件同名且是私有。在C#中,你可以访问到这个字段,因为它真的就是一个字段。
    换言之,在C#中写代码时,如果是在类的内部使用事件,其实就是引用那个自动生成的私有字段(委托字段)。
    而在类的外部使用事件,是不同于在类的内部使用事件(因为这个字段是私有的,所以在类的外部也就访问不到)。

    event 本质上所做的工作应该还是通过 delegate 来实现的,或者至少原理相同。event 关键字只不过是让CLR给所定义的 delegate 对象进行一个封装。
    event 是通过对 delegate 的限制来封装一部分本来就不应该暴露在外的行为,从而更符合面向对象的思想(封装的原则)。


    附加:
    1、事件其实是由三个方法add、remove和raise组成的。但C#编译器总是不会生成raise方法。
    2、自动事件不同的编译器实现是不同的,例如VB的编译器生成的私有字段是(事件名)Event。
    3、Web开发中的Control也是事件驱动的。


    参考来源:
    http://www.cnblogs.com/Ivony/archive/2009/09/10/1563876.html
    http://www.cnblogs.com/jujusharp/archive/2008/11/01/CSharp-delegate-event-difference.html

    推荐阅读:[叩响C#之门]写给初学者:自定义事件
  • 相关阅读:
    python threading 无法并行问题
    flask
    jinjia2 模板不解析html
    docker 配置lnmp环境(mac环境下)
    docker基础
    django初体验
    Centos6.5 编译安装Mysql 5.5.3.7
    Mysql InnoDB事务
    删除GitHub上项目中的某个文件
    转 WPF MVVM 循序渐进 (从基础到高级)
  • 原文地址:https://www.cnblogs.com/xugang/p/1723254.html
Copyright © 2011-2022 走看看