zoukankan      html  css  js  c++  java
  • 换个角度看委托

    毛主席说过长征是宣言书,长征是宣传队,长征是播种机。那么委托是什么呢?
     

    阅读目录:

    一、 委托是函数模板

    二、委托是函数指针

    三、委托是函数指针集合

    四、委托是事件通知

    五、委托是外部帮手

    六、.net中定义的丰富多彩的委托

    一、 委托是函数模板

    和类做对比, 类是对象的模板, 那么委托就是函数的模板.
    先看看平常我们如何定义一个class
    public class ClassA{
    }
    如上,我们使用关键字class来定义一个类.
     
    对于委托,我们使用delagate来定义:
    public delegate void MyDelegate(string a);
    我们定义了一个MyDelegate类型, 它定义的函数模板要求: 函数有个sting类型的参数, 没有返回值.
     

    二、 委托是函数指针

    使用定义好的委托类型,就可以创建这种类型的变量,并且为这种类型的变量赋值.
    一个具体的委托变量就是一个函数指针,它指向一个函数的入口,当调用这个委托的时候,就相当于调用这个函数
    • 使用函数赋值
    void ShowMessage(string message)
    {
        Console.WriteLine(message);
    }
    那么我们可以这样写
    var myDelegate = new MyDelegate(ShowMessage); //创建了一个委托变量,为委托变量赋值
    myDelegate("hello"); //直接调用委托, 相当于调用了方法ShowMessage.
     
    还可以赋值:
    MyDelegate myDelegate = ShowMessage;
     
    • 使用匿名方法赋值
    MyDelegate myDelegate = delegate(string message) { Console.WriteLine(message);} //创建了一个委托变量,使用匿名函数赋值
    myDelegate("hello"); //直接调用委托, 相当于调用了方法ShowMessage.
     
    • 使用lambda表达式赋值
    MyDelegate myDelegate = message => Console.WriteLine(message)//创建了一个委托变量,使用lambda赋值
    myDelegate("hello"); //直接调用委托, 相当于调用了方法ShowMessage.
     
     

    三. 委托是函数指针集合

    MyDelegate myDelegate = message => Console.WriteLine(message);//创建了一个委托变量,使用lambda赋值
    myDelegate += ShowMessage;//对委托变量,增加一个函数
    myDelegate("hello");
     
    public static void ShowMessage(string message)
    {
        Console.WriteLine(message + "1");
    }
    输出结果是
     
    可以看到, 我们在调用myDelegate的时候, 输出了2个message(hello和hello1), 一个是lambda表达式定义的函数,一个是ShowMessage函数
    这里委托就像是一个函数指针的集合类,包含了对2个方法的引用,当调用该委托的时候,就调用了这2个方法。
     

    四. 委托是事件通知

    假设当前你要设计一个仓库类,每个仓库都有一定的大小,当超过了仓库大小的时候, 你要把这个事件报告出来. 其它类可以容易的获取到这个事件和处理这个事件。
    class Program
    {
        static void Main(string[] args)
        {
            var warehouses = new Warehouses(100);//定义了一个大小是100的仓库
            warehouses.WarehousesOverFlowEvent += WhenWarehousesOverFlow;//对仓库进行监控
            warehouses.Add(120);
            Console.ReadLine();
        }
        static void WhenWarehousesOverFlow(Warehouses warehouses, int changeNumber)//这个是对于仓库溢出的处理函数
        {
             Console.WriteLine("The current warehouse is overflow, we need do something.");
        }
    }
     
    public delegate void WarehousesOverFlow(Warehouses warehouses, int changeNumber);//定义委托类型,从名字很容易明白这个委托是用来通知仓库溢出的事件的.
    public class Warehouses
    {
        private readonly int _storesSize;
        private int _currentSize = 0;
        public WarehousesOverFlow WarehousesOverFlowEvent { set; get; }//定义了一个public的委托, 任何外界对象对于该仓库的溢出感兴趣的对象,都可以为WarehousesOverFlowEvent指定一个具体的响应函数
        public Warehouses(int storesSize)
        {
            _storesSize = storesSize;//在构造函数中,指定了仓库的size
        }
        public bool Add(int number)
        {
            if(_currentSize + number > _storesSize)//如果添加的货物数量大于了size, 就通过委托通知外界
            {
                 if (WarehousesOverFlowEvent != null) WarehousesOverFlowEvent(this, number);
                 return false;
            }
            _currentSize += number;
            return true;
         }
    }
    运行之后的结果会看到:
     
    我们熟悉的asp.net和winform中的事件event也是委托. 上面的例子中, 对于面向对象的"开放封闭"原则, 通过委托就非常优雅的实现了。它封闭了仓库自己的功能, 同时又开放了外界获取信息的渠道。
     

    五. 委托是外部帮手

    下面的例子中, 实现了一个Log类, 用来记录日志,但是log类真实的记录动作不是有它自己完成的,而是通过委托完成的. 这里的委托就充当了一个外部帮手中介的角色.
    当我们为它的委托指定为ConsoleWriter的时候, 就把日志输出到控制台
    当为它指定为FileWriter的时候,就把日志输出到文件
    当指定为DbWriter的时候,它又把日志输出到数据库了。
     
    class Program
    {
        static void Main(string[] args)
        {
            var log = new Log();
            log.WriteMessage += ConsoleWriter; //为委托指定为控制台输出
            Console.ReadLine();
        }
        //输出日志到控制台
        static void ConsoleWriter(string message)
        {
            Console.WriteLine(message);
        }
        static void FileWriter(string message)
        {
            ........
        }
        static void DbWriter(string message)
        {
            ........
        }
    }
    public delegate void WriteMessage(string message);
    public class Log
    {
        public WriteMessage WriteMessage { get; set; }
        public void Debug(string message)
        {
            if (WriteMessage != null) WriteMessage(message);
        }
        public void Info(string message)
        {
            if (WriteMessage != null) WriteMessage(message);
        }
    }
     

    六. .net中定义的丰富多彩的委托

    • EventHandler
    其定义public delegate void EventHandler(object sender, System.EventArgs e)
    • Func
    其定义之一:public delegate TResult Func<in T1,in T2,out TResult>(T1 arg1, T2 arg2)
    • Action
    其定义之一:public delegate void Action<in T>(T obj)
    • Predicate
    其定义:public delegate bool Predicate<in T>(T obj)
    有了.net中已经为我们定义好了的委托类型,能够满足我们的大部分需求了,所以在使用委托的时候,尽量避免定义过多的委托类型.
  • 相关阅读:
    我用柔软打败你
    【记录】ASP.NET URL 特殊字符
    再次记录 Visual Studio 2015 CTP 5 的一个坑
    【记录】ASP.NET MVC View 移动版浏览的奇怪问题
    升级 Visual Studio 2015 CTP 5 的坑、坑、坑
    OWIN 中 K Commands 与 OwinHost.exe 相等吗?
    OWIN 中 K Commands(OwinHost.exe)与 Microsoft.AspNet.Hosting 的角色问题
    深入理解 OWIN 中的 Host 和 Server
    【续集】在 IIS 中部署 ASP.NET 5 应用程序遭遇的问题
    delete
  • 原文地址:https://www.cnblogs.com/JustRun1983/p/What_is_Delegate.html
Copyright © 2011-2022 走看看