去年学习C#的时候按照进度把C#的委托和事件“认真”的学习了一下,自己知道委托和事件的重要性,所以也努力的学习,可说实也没怎么学懂。碰巧这段时间在做一个解析GPS数据的小项目,因为其中有需要条件自动判断并处理的模块,因此首先想到的就是委托和事件。借此机会重新学习和复习了一下,收获颇丰。

  什么是委托?根据我的理解委托就是把一件可能发生的事情,当满条件达到时委托别人帮忙处理。根据从书上看到的委托应该是有C++的函数指针发展而来的,只不过C#中一般不用指针。在这里举一个小例子,输入一个字符串当它的长度满足指定长度时输出,达到指定长度就是触发了事件。

class AutoDisposeStr
    {

public AutoDisposeStr(int length)
        {
            LimitLength = length;
        }
        public delegate void DisplaysrtHandler();
        public  DisplaysrtHandler MeetLength;

public void OnReadAndDisplay()
        {
            Console.WriteLine(str);
        }

public DisplaysrtHandler MeetLength
        {
           get { return _MeetLength; }
           set { _MeetLength = value; }
        }
        public int LimitLength
        {
            get { return _LimitLength; }
            set { _LimitLength = value; }
        }

public string str
        {
            get { return _str; }
            set
            {
                if (value.Length >= LimitLength)
                {
                    _str = value;
                    MeetLength();
                }
            }
        }

private int _LimitLength;
        private string _str;
        private DisplaysrtHandler _MeetLength;
    }
}

  首先构建了一AutoDisposeStr类有三个字段_LimitLength表示处理字符串的门限值对应的属性为LimitLength,_Str将要处理的字符串对应属性为Str,_MeetLength为委托类型的字段对应属性为MeetLength用来注册监听者。需要注意的是委托类型参数列表和你处理函数的参数列表需要对应,在这里就是 public delegate void DisplaysrtHandler()和public void OnReadAndDisplay()。因为要实时监听字符串长度是否达到门限值,所以要在字符串属性赋值时进行处理。每输入一个字符串,判断长度是否达到门限值,如果达到则调用监听函数处理:

public string str
        {
            get { return _str; }
            set
            {
                if (value.Length >= LimitLength)
                {
                    _str = value;
                    MeetLength();//调用监听函数处理
                }
            }

在这里其实就是把处理的方法委托给了public void OnReadAndDisplay()函数。最后只需要在Main()函数中实例化并注册监听函数即可。委托的用法就这么简单,不过有几点组要注意:

  一:如果当前没有订阅者也就是MeetLength为空执行 MeetLength()会引发异常NullReferenceException,因此为了解决这个问题在触发事件之前检查空值。

DisplaysrtHandler local=MeetLength;

if(local!=null)

{

  local();

}

这里定义了一个局部变量来检查是否为空是为了防止来自不同线程订阅者被移除可能造成NullReferenceException异常,因为MeetLength-=<listener>,会将一个全新的委托指派给MeetLength,这不会对原先local委托有任何影响。

    二,委托链会按注册的顺序调用,但是如果一旦前面的委托发生异常,后面的委托将得不到执行。因此最保险的方法应该用foreach(DisplaysrtHandler myhander in local.GetInvocationList){}同时加上异常处理。

委托就说这么多吧,说的不对的地方欢迎指正共同学习。

接下来说说事件,我感觉事件就是在委托的基础上增加了一些编程的规范。对于委托你可以在任何包容类之外调用委托,这就会造成对包容类内委托结果的影响。不满足封装性要求,其次事件中当注册事件和移除事件时如果不幸将“-=”或“+=”写成了“=”在委托中没有语法错误而是造成了委托连被无意赋值号覆盖掉了,而在事件中这样的大意是不能编译通过的。防止了这种错误的可能性,还有事件中对事件处理函数参数有规范要求,这里就不多讲了。贴上事件的代码以做对比:

class AutoDisposeStr
    {

public class AutoDisposeStrArgs : System.EventArgs
        { }
        public AutoDisposeStr(int length)
        {
            LimitLength = length;
        }
        public delegate void DisplaysrtHandler(object sender, AutoDisposeStrArgs newAutoDisposeStr);
        public event DisplaysrtHandler MeetLength;

public void OnReadAndDisplay(object sender, AutoDisposeStrArgs newAutoDisposeStr)
        {
            Console.WriteLine(str);
        }

//public DisplaysrtHandler MeetLength
        //{
        //    get { return _MeetLength; }
        //    set { _MeetLength = value; }
        //}
        public int LimitLength
        {
            get { return _LimitLength; }
            set { _LimitLength = value; }
        }

public string str
        {
            get { return _str; }
            set
            {
                if (value.Length >= LimitLength)
                {
                    _str = value;
                    MeetLength(this,null);
                }
            }
        }

private int _LimitLength;
        private string _str;
        //private DisplaysrtHandler _MeetLength;
    }

主函数:

class Program
    {
        static void Main(string[] args)
        {
            AutoDisposeStr ads= new AutoDisposeStr(5);
            ads.MeetLength += ads.OnReadAndDisplay;
            for (int i = 0; i < 10; i++)
            {
                ads.str = Console.ReadLine();
            }
        }

本人也是初学者,有说的不对不妥的地方欢迎指正,共同学习,共同进步。

重读C#委托、事件有感的更多相关文章

  1. C# ~ 从 委托事件 到 观察者模式 - Observer

    委托和事件的部分基础知识可参见 C#/.NET 基础学习 之 [委托-事件] 部分: 参考 [1]. 初识事件 到 自定义事件: [2]. 从类型不安全的委托 到 类型安全的事件: [3]. 函数指针 ...

  2. C#委托,事件理解入门 (译稿)

    原文地址:http://www.codeproject.com/Articles/4773/Events-and-Delegates-Simplified 引用翻译地址:http://www.cnbl ...

  3. 关于ios使用jquery的on,委托事件失效

    $('.parents').on("click",'.child',function(){}); 类似上面这种,在ios上点击"child"元素不会起作用,解决 ...

  4. Observer设计模式中-委托事件-应用在消息在窗体上显示

    Observer设计模式:监视者模式.在类中的方法中处理的结果或者消息通过事件委托 的方式发送给主窗体. 因为在其它类中直接访问主窗体类,显示内容是不能直接调用控件赋值的,当然也有别的类似查阅控件名, ...

  5. Asp.net用户控件和委托事件

    在Asp.net系统制作过程中,门户类型的网站,我们可以用DIV+CSS+JS+Ajax全部搞定,但是一旦遇到界面元素比较复杂的时候,还是UserControl比较方便一些,各种封装,各种处理,然后拖 ...

  6. jQuery里面的普通绑定事件和on委托事件

    以click事件为例: 普通绑定事件:$('.btn1').click(function(){}绑定 on绑定事件:$(document).on('click','.btn2',function(){ ...

  7. c#基础学习笔记-----------委托事件

    这里有一个比较简单的委托实例应用(跨窗体操作控件) http://blog.csdn.net/bdstjk/article/details/7004035 还有一个比较详细的介绍并深入理解委托事件的讲 ...

  8. c#委托事件入门--第二讲:事件入门

    上文 c#委托事件入门--第一讲:委托入门 中和大家介绍了委托,学习委托必不可少的就要说下事件.以下思明仍然从事件是什么.为什么用事件.怎么实现事件和总结介绍一下事件 1.事件是什么:. 1.1 NE ...

  9. Unity C#笔记 委托&事件

    C#的委托与事件搭配,即是观察者模式的一种实现. 因为观察者模式的原理很易懂,不作多讲,本文纯粹用于记录语法. delegate(委托) //声明没有参数,没有返回值的委托类型XXXX public ...

  10. JavaScript中事件委托(事件代理)详解

    在JavaScript的事件中,存在事件委托(事件代理),那么什么是事件委托呢? 事件委托在生活中的例子: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托 ...

随机推荐

  1. AngularJs $q 承诺与延迟

    $q 一个帮助处理异步执行函数的服务.当他们做完处理时,使用它们的返回值(或异常). 受 Kris Kowa’s Q 的启发,这是一个实现promise/deferred对象的启用. $q的两种方式- ...

  2. [Android]Unit Test for Android

    根据Android Developer文档,对Android的UT做个学习总结: 1. 搭建Eclipse测试环境. Eclipse的ADT(Android Developer Tools) 插件为我 ...

  3. 【Beta】Daily Scrum 第一天

    [目录] 1.任务进度 2.困难及解决 3.燃尽图 4.代码check-in 5.总结 1. 任务进度 学号 已完成 接下来要完成的 612 添加计时界面返回按键事件,添加SharePreferenc ...

  4. PL/0编译器(java version) – SymbolTable.java

    1: package compiler; 2: //竟然没有对符号表检查大小,会溢出的. 3:   4: import java.io.IOException; 5:   6: public clas ...

  5. CF724C: Ray Tracing

    传送门 CF的题质量真心不低,这道题的标准解法(应该)是exgcd,打比赛的时候想到了具体的推导公式了,也意识到了需要用exgcd,但是因为寝室要锁门了(其实就是太弱,就放弃了. 首先很显然,这条线所 ...

  6. static静态变量的理解

    静态变量 类型说明符是static.静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在 静态存储区内分配存储单元),该区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间 ...

  7. Java递归算法——三角数字

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  8. Maven打包可执行jar

    参考文献:http://blog.csdn.net/xiao__gui/article/details/47341385 方法:使用assembly插件,生成的jar包名为xxx-jar-with-d ...

  9. 一张图总结docker命令

  10. C# vs C++ Performance

    http://www.codeproject.com/Articles/212856/Head-to-head-benchmark-Csharp-vs-NET