一瓶牛奶和一张报纸引发的 “ 委托 ” 事件

委托的定义 (What)
 
A delegate declaration defines a reference type that can be used to encapsulate a method with a specific signature. A delegate instance encapsulates a static or an instance method. Delegates are roughly similar to function pointers in C++; however, delegates are type-safe and secure.
                                                                                                         MSDN Microsoft
C# delegate is a callback function. It is smarter then “standard” callback because it allows defining a strict list of parameters which are passed from class-server to class-client.
                                                                                                        
委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值
                                                     C# 编程指南
 
委托与 C++函数指针区别
 
l          一个 delegate object 一次可以搭载多个方法,而不是一次一个。当我们唤起一个搭载了多个方法的 delegate ,所有方法以其“被搭载到 delegate object 的顺序”被依次唤起
l          一个 delegate object 所搭载的方法并不需要属于同一个类。一个 delegate object 所搭载的所有方法必须具有相同的原型和形式。然而,这些方法可以即有 static 也有 non-static ,可以由一个或多个不同类的成员组成。
l          一个 delegate type 的声明在本质上是创建了一个新的 subtype instance ,该 subtype 派生自 .NET library framework 的 abstract base classes Delegate 或 MulticastDelegate ,它们提供一组 public methods 用以询访 delegate object 或其搭载的方法。
 
对委托的个人理解
 
委托是函数的封装,它代表一“类”函数。它们都符合一定的签名:拥有相同的参数列表、返回值类型。同时,委托也可以看成是对函数的抽象,是函数的“类”。此时,委托的实例将代表一个具体的函数。
 
为什么要使用委托?
更加灵活的方法调用
用于异步回调
多线程编程中使用委托来指定启动一个线程时调用的方法
C# 中的事件模型。用它们指明处理给定事件的方法
 
如何委托
 
<modifiers> delegate <return_type> <delegate_name> ( argument_list )
 
public delegate void Del( string message);
 
public void DelegateMethod( string message)
{
    System.Console.WriteLine(message);
}
Del handler = new Del (obj.DelegateMethod);
handler( "Hello World");
 
先声明委托,再实例化并指明所代具体方法
 
委托应用——异步回调
 
异步回调:由于实例化委托是一个对象,所以可以将其作为参数进行
传递,也可以将其赋值给属性。这样,方法便可以将一个委托作为参
数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的
进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使
用委托的代码无需了解有关所用方法的实现方面的任何信息。
 
public void MethodWithCallback( int param1, int param2, Del callback
{
    callback( "The number is: " + (param1 + param2).ToString());
}
MethodWithCallback(1, 2, handler);
 
回调的另一个常见用法是定义自定义的比较方法并将该委托传递给排序方法。
 
委托实现回调类似于接口所实现的封装?
 
何时委托?何时接口?
在以下情况中使用委托:
当使用事件设计模式时。
当封装静态方法可取时。
当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
需要方便的组合。
当类可能需要该方法的多个实现时。
在以下情况中使用接口:
当存在一组可能被调用的相关方法时。
当类只需要方法的单个实现时。
当使用接口的类想要将该接口强制转换为其他接口或类类型时。
 
【实例代码】
先看看使用接口的例子
// 先定义两个接口用于报纸、牛奶,然后订阅者继承这个接口
public interface IMilkBox
{
    void PutMilkIn( string s);
}
 
public interface INewsPaperBox
{
    void PutNewsPaperIn( string s);
}
 
public class Subscriber : INewsPaperBox, IMilkBox
{
    public string name;
 
    public Subscriber( string name)
    {
        this.name = name;
    }
 
    public void PutNewsPaperIn( string s)
    {
        Console.WriteLine( "{0} 在报箱里收到送来的 {1}" , name, s);
    }
 
    public void PutMilkIn( string s)
    {
        Console.WriteLine( "{0} 在奶箱里收到送来的 {1}" , name, s);
    }
}
 
public class NewsPaperSender
{
    // 接口实现
    protected ArrayList subscribers = new ArrayList();
 
    public void SendNewsPaper()
    {
        foreach ( INewsPaperBox newsPaperBox in subscribers)
            newsPaperBox.PutNewsPaperIn( " 报纸 " );
    }
 
    public void Subscribe( INewsPaperBox newsPaperBox)
    {
        subscribers.Add(newsPaperBox);
    }
}
 
public class MilkSender
{
    // 接口实现
    protected ArrayList subscribers = new ArrayList();
 
    public void SendMilk()
    {
        foreach ( IMilkBox milkBox in subscribers)
            milkBox.PutMilkIn( " 牛奶 " );
    }
    public void Subscribe( IMilkBox milkBox)
    {
        subscribers.Add(milkBox);
}
}
// 功能的实现
public static void Main( string[] args )
{
    // 接口实现
    MilkSender ms = new MilkSender();
    NewsPaperSender nps = new NewsPaperSender();
    Subscriber s1 = new Subscriber( " 张三 " );
    Subscriber s2 = new Subscriber( " 李四 " );
    Subscriber s3 = new Subscriber( " 王五 " );
 
    ms.Subscribe(s1);
    ms.Subscribe(s2);
    nps.Subscribe(s2);
    nps.Subscribe(s3);
    ms.SendMilk();
    nps.SendNewsPaper();
}
这里我们看看利用接口实现存在的问题:不能达到箱子的共享,每个接口都只能实现特定功能
 
再看看利用委托实现牛奶和报纸的订阅来解决上面的问题:使用委托让牛奶报纸共享箱子
namespace myDelegate
{
    public delegate void SendableDelegate( string s);
 
    public class Subscriber
    {
        public string name;
 
        public Subscriber( string name)
        {
            this.name = name;
        }
 
        public void PutNewsPaperIn( string s)
        {
            Console.WriteLine( "{0} 在报箱里收到送来的 {1}" , name, s);
        }
 
        public void PutMilkIn( string s)
        {
            Console.WriteLine( "{0} 在奶箱里收到送来的 {1}" , name, s);
        }
    }
 
    public class NewsPaperSender
    {
        // 委托实现
        public event SendableDelegate SendNewsPaperHandler;
 
        public void SendNewsPaper()
        {
            if (SendNewsPaperHandler != null)
                SendNewsPaperHandler( " 报纸 " );
        }
 
        public void Subscribe( SendableDelegate sd)
        {
            SendNewsPaperHandler += sd;
        }
    }
 
    public class MilkSender
    {
        // 委托实现
        public event SendableDelegate SendMilkHandler;
 
        public void SendMilk()
        {
            if (SendMilkHandler != null)
                SendMilkHandler( " 牛奶 " );
        }
 
        public void Subscribe( SendableDelegate sd)
        {
            SendMilkHandler += sd;
        }
    }
    // 功能的实现
    public class Client
    {
       
        public static void Main( string[] args )
        {
            // 委托实现
            MilkSender ms = new MilkSender();
            NewsPaperSender nps = new NewsPaperSender();
            Subscriber s1 = new Subscriber( " 张三 " );
            Subscriber s2 = new Subscriber( " 李四 " );
            Subscriber s3 = new Subscriber( " 王五 " );
 
            ms.Subscribe( new SendableDelegate(s1.PutMilkIn));
            ms.Subscribe( new SendableDelegate(s2.PutMilkIn));
            nps.Subscribe( new SendableDelegate(s2.PutNewsPaperIn));
            nps.Subscribe( new SendableDelegate(s3.PutMilkIn));
            ms.SendMilk();
            nps.SendNewsPaper();        
        }
    }
}
 
多播委托
 
多播委托——引用多个方法的委托,它连续调用每个方法。委托必须是同类型的,返回类型必须是 void,不能带输出参数(可以带引用参数)。多播委托应用于事件模型中。
 
最后看看异步回调和多播的例子
class Program
{
    public delegate void del( string msg);
 
    static void Main( string[] args)
    {
        DelClass myDel= new DelClass();
        del handle = new del(myDel.printMsg);
        handle( "hello world");
       
        DelHandle myHandle = new DelHandle();
        handle = new del(myHandle.hangleMsg);
        handle( "handle msg");
 
        // 异步回调
        printAllMsg( "call", "back", handle);
 
        // 多播
        del d1 = myDel.method1;
        del d2 = myDel.method2;
        del d3 = myDel.printMsg;
        del allMethod = d1 + d2;
        allMethod += d3;
 
        allMethod( "all method ");
 
        Console.ReadLine();
    }
 
    private static void printAllMsg( string param1, string param2, del myCallBack)
    {
        myCallBack(param1 + param2);
    }
}
 
public
CodeProject
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的体育馆管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本体育馆管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此体育馆管理系统利用当下成熟完善的SpringBoot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线选择试题并完成答题,在线查看考核分数。管理员管理收货地址管理、购物车管理、场地管理、场地订单管理、字典管理、赛事管理、赛事收藏管理、赛事评价管理、赛事订单管理、商品管理、商品收藏管理、商品评价管理、商品订单管理、用户管理、管理员管理等功能。体育馆管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:体育馆管理系统;SpringBoot框架;Mysql;自动化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值