开发者社区> 老朱教授> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

再探委托与事件

简介:
+关注继续查看


委托 

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

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

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

 

示例一:委托作为参数

复制代码
ExpandedBlockStart.gif委托作为参数.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));
        }
    }
}
复制代码


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

复制代码
ExpandedBlockStart.gif委托调用内部类的方法.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/xugang/archive/2010/04/28/1723254.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
C# 从1到Core--委托与事件(三)
委托与事件在C#1.0的时候就有了,随着C#版本的不断更新,有些写法和功能也在不断改变。本文温故一下这些改变,以及在NET Core中关于事件的一点改变。
33 0
C# 从1到Core--委托与事件(二)
 委托与事件在C#1.0的时候就有了,随着C#版本的不断更新,有些写法和功能也在不断改变。本文温故一下这些改变,以及在NET Core中关于事件的一点改变。
35 0
事件
事件三要素、事件类型、事件绑定方式
68 0
C# 委托 事件 匿名方法
(*) 委托 delegate 从最简单的例子开始: namespace ConsoleApplication1 { class Program { // 委托其实就相当于一个类型。这里,类型的名字叫BinaryOp public delegate int BinaryOp(int x, int y); static p
1072 0
C#基础知识回顾--委托事件
在上一篇看到他我一下子就悟了(续)---委托,被人狂喷。说写的太空,没有什么内容之类的。所以准备在这里重写下,不过还是按着以前的方式尽量简单的写。这里我们以打篮球为例。 第一步:首先,其他对象订购事件        当发球的球员产生它的发球事件之前,其他球员需要订购这个事件,采用这种方式,只要出现一个发球事件,其他球 员就能够知道。
624 0
jquery 获取回车键事件
$(document).ready(function(){ $("html").die().live("keydown",function(event){ if(event.
599 0
+关注
3545
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载