热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

delegatevs.event(多谢Cavingdeep兄的指正,等待更新……)

首先说明,event其实也是一种delegate,为了区分,我们称一般的delegate为“plaindelegate”。写代码的过程中,经常会在delegate和event之间进行选择,以前也
首先说明,event其实也是一种delegate,为了区分,我们称一般的delegate为“plain delegate”。

写代码的过程中,经常会在delegate和event之间进行选择,以前也没仔细思考选择的原因,今天终于忍不住花了半天时间仔细琢磨了一下……好了,直接拿代码说话吧:

using  System;

namespace  EventAndDelegate
{
    
public delegate void TestDelegate(string s);

    
public interface ITest {
        
// 【区别】 1. event可以用在interface中,而plain delegate不可以(因为它是field)
        event TestDelegate TestE;   // Passed
        TestDelegate TestD;         // Error: Interfaces cannot contain fields
    }


    
public class Parent {
        
public event TestDelegate TestE;
        
public TestDelegate TestD;

        
protected void RaiseTestE(string s)
        
{
            TestE(s);   
// The event 'EventAndDelegate.Parent.TestE' can only
                        
// be used from within the type 'EventAndDelegate.Parent'
        }

    }


    
public class Child : Parent {
        
void ChildFunc()
        
{
            
// 【区别】 2. event不允许在声明它的class之外(即使是子类)被调用(除此之外只能用于+=或-=),而plain delegate则允许
            TestD("OK");        // Passed
            TestE("Failure");   // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
                                
//        the left hand side of += or -= (except when used from within
                                
//        the type 'EventAndDelegate.Parent')

            
// 【补充】 在子类中要触发父类声明的event,通常的做法是在父类中声明一个protected的Raisexxx方法供子类调用
            RaiseTestE("OK");   // The class 'EventAndDelegate.Child' can only call the
                                
// 'EventAndDelegate.ParentRaiseTestE' method to raise the event
                                
// 'EventAndDelegate.Parent.TestE'

            
// 【区别】 同2#
            object o1 = TestD.Target;
            
object o2 = TestE.Target;   // The class 'EventAndDelegate.Child' can only call the
                                        
// 'EventAndDelegate.ParentRaiseTestE' method to raise the event
                                        
// 'EventAndDelegate.Parent.TestE'

            
// 【区别】 同2#
            TestD.DynamicInvoke("OK");
            TestE.DynamicInvoke(
"OK");   // The class 'EventAndDelegate.Child' can only call the
                                        
// 'EventAndDelegate.ParentRaiseTestE' method to raise the event
                                        
// 'EventAndDelegate.Parent.TestE'
        }

    }


    
class Other
    
{
        
static void Main(string[] args)
        
{
            Parent p 
= new Parent();

            p.TestD 
+= new TestDelegate(p_Test1);   // Passed
            p.TestE += new TestDelegate(p_Test1);   // Passed

            
// 【区别】 3. event不允许使用赋值运算符,而plain delegate则允许。
            
//             注意,对plain delegate,使用赋值运算符意味着进行了一次替换操作!
            p.TestD = new TestDelegate(p_Test2);   // Passed
            p.TestE = new TestDelegate(p_Test2);   // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
                                                   
//        the left hand side of += or -= (except when used from within
                                                   
//        the type 'EventAndDelegate.Parent')

            
// 【区别】 同2#
            p.TestD("OK");      // Passed
            p.TestE("Failure"); // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
                                
//        the left hand side of += or -= (except when used from within
                                
//        the type 'EventAndDelegate.Parent')
        }


        
static void p_Test1(string s)
        
{
            Console.WriteLine(
"p_Test1: " + s);
        }


        
static void p_Test2(string s)
        
{
            Console.WriteLine(
"p_Test2: " + s);
        }

    }

}



分析:

  1. plain delegate与event的关系类似于field与Property(实事上前者就是field,或者我们可以把event看成是一种特殊的Property)
  2. 正是由于1#,在使用上,plain delegate几乎没有任何限制,而event则有严格的限制(只能用在+=和-=的左边)

结论

  1. event更面向对象一些。
  2. 当我们需要灵活时,直接使用plain delegate;反之,需要严格的控制时,使用event。
  3. 由于event不能使用赋值运算符,因此有时我们要求一个事件在任何时刻只能有一个响应方法时,我们使用plain delegate更为方便。
  4. ……(大家补充)

推荐阅读
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 本文旨在探讨Swift中的Closure与Objective-C中的Block之间的区别与联系,通过定义、使用方式以及外部变量捕获等方面的比较,帮助开发者更好地理解这两种机制的特点及应用场景。 ... [详细]
  • 本文探讨了如何使用Scrapy框架构建高效的数据采集系统,以及如何通过异步处理技术提升数据存储的效率。同时,文章还介绍了针对不同网站采用的不同采集策略。 ... [详细]
  • Java多线程售票案例分析
    本文通过一个售票系统的实例,深入探讨了Java中的多线程技术及其在资源共享和并发控制中的应用。售票过程涉及查询、收款、找零和出票等多个步骤,其中对总票数的管理尤为关键。 ... [详细]
  • 本文详细介绍了如何使用C#实现不同类型的系统服务账户(如Windows服务、计划任务和IIS应用池)的密码重置方法。 ... [详细]
  • 使用Java计算两个日期之间的月份数
    本文详细介绍了利用Java编程语言计算两个指定日期之间月份数的方法。文章通过实例代码讲解了如何使用Joda-Time库来简化日期处理过程,旨在为开发者提供一个高效且易于理解的解决方案。 ... [详细]
  • iOS如何实现手势
    这篇文章主要为大家展示了“iOS如何实现手势”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“iOS ... [详细]
  • 本文介绍了如何使用 Python 的 Pyglet 库加载并显示图像。Pyglet 是一个用于开发图形用户界面应用的强大工具,特别适用于游戏和多媒体项目。 ... [详细]
  • Gradle 是 Android Studio 中默认的构建工具,了解其基本配置对于开发效率的提升至关重要。本文将详细介绍如何在 Gradle 中定义和使用共享变量,以确保项目的一致性和可维护性。 ... [详细]
  • 本文介绍了使用Python和C语言编写程序来计算一个给定数值的平方根的方法。通过迭代算法,我们能够精确地得到所需的结果。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • C/C++ 应用程序的安装与卸载解决方案
    本文介绍了如何使用Inno Setup来创建C/C++应用程序的安装程序,包括自动检测并安装所需的运行库,确保应用能够顺利安装和卸载。 ... [详细]
  • 最近遇到了一个关于单链表的编程问题,这是来自福富公司的笔试题目。以往我通常使用C语言来解决这类问题,但这次决定尝试用Java来实现。该题目要求实现一个单链表,并完成特定的方法。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • 本文基于Java官方文档进行了适当修改,旨在介绍如何实现一个能够同时处理多个客户端请求的服务端程序。在前文中,我们探讨了单客户端访问的服务端实现,而本篇将深入讲解多客户端环境下的服务端设计与实现。 ... [详细]
author-avatar
手机用户2502926053_634
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有