zoukankan      html  css  js  c++  java
  • .net 中的委托(delegate)的使用和原理

    .net中的委托,我个人认为很类似于C++ 中的函数指针。你定义一个代理,然后注册函数到这个代理中即可使用。
    通过下面的例子来讲解.net中委托的使用
    using System;
    using System.IO;
    using System.Windows.Forms;
    class Set
    {
    private Object[] items;
    //构造器。给对象数组进行初始化
    public Set(Int32 numItems)
    {
    items = new Object[numItems];
    for(Int32 i = 0; i < numItems; i++)
    {
    items[i] = i;
    }
    }
    //定义一个FeedBack委托类
    public delegate void FeedBack(Object value, Int32 item; Int32 numItems);
    public void ProcessItems(FeedBack feedback)
    {
    for(Int32 i = 0; i < items.Length; items++)
    {
    if(feedback!=null)
    {
    //如果指定有回调函数,则调用它们
    feedback(items[item]; item + 1; items.Length);
    }
    }
    }
    }
    //定义一个应用类来应用委托
    class App
    {
    public static void main()
    {
    StaticCallBack();
    InstanceCallBack();
    }
    public static void StaticCallBack()
    {
    //设定含有5个Object的Set对象
    Set setOfItem = new Set[5];
    //处理items元素,但不给任何反馈
    setOfItem.ProcessItems(null);   -----------1
    Console.WriteLine();
    //处理items元素,并将反馈输出到控制台上
    setOfItem.ProcessItems(new Set.FeedBack(App.FeedBackToConsole));//注册代理---2
    Console.WriteLine();
    //处理items元素,并将反馈输出到消息框上
    setOfItem.ProcessItems(new Set.FeedBack(App.FeedBackToMsgBox));//注册代理 ---3
    Console.WriteLine();
    //处理items元素,并将反馈同时输出到控制台和消息框中
    FeedBack fb = null;
    fb += new Set.FeedBack(App.FeedBackToConsole);
    fb += new Set.FeedBack(App.FeedBackToMsgBox);
    setOfItems.ProcessItems(fb);  --------4
    Console.WriteLine();
    }
    static void FeedBackToConsole(Object value, Int32 item; Int32 numItems)
    {
    Console.WriteLine(String.Format("Processing item{0} of {1}:{2}",item, numItems, value));
    }
    static void FeedBackToConsole(Object value, Int32 item; Int32 numItems)
    {
    MessageBox.Show(String.Format("Processing item{0} of {1}:{2}",item, numItems, value));
    }
    static void InstanceCallBack()
    {
    //设定含有5个Object的Set对象
    Set setOfItem = new Set[5];
    //处理items元素,并将反馈输出到一个文件中
    App appobj = new App();
    setOfItems.ProcessItem(new Set.FeedBack(appobj.FeedBackToFile)); -------5
    Console.WriteLine();
    }
    public void FeedBackToFile(Object value, Int32 item; Int32 numItems)
    {
    StreamWriter sw = new StreamWriter("status",true);
    sw.WriteLine(String.Format("Processing item{0} of {1}:{2}",item, numItems, value));
    sw.Close();
    }
    }
    在上面的程序中,包括5此对FeedBack委托的使用,也就是调用Set类的ProcessItem静态方法。第一次ProcessItem的参数为空,表示不使用委托。
    第二次调用ProcessItem方法时,它首先构造了一个新的Set.FeedBack委托对象(至于这个对象的具体东西,会在后面有解释)。在将FeedBackToConsole方法作为参数传递给FeedBack构造器,并将返回值作为ProcessItem的参数传递过去。
    第三次调用和第二次差不多,只是调用的函数不同罢了。
    第四次调用为我们展示了怎样把委托对象链接成一个委托链。C#中的+= 操作符用来把委托对象追加到fb引用的委托对象链表上。
    第五次调用的不同之处在于,传递的方法是一个实例方法而不是一个静态方法。
    下面我们来揭开委托神秘的面纱:
    再类看一遍下面这行代码:
    public delegate void FeedBack(Object value, Int32 item; Int32 numItems);
    当编译器遇到这行代码时,它会产生如下面所示的一个完整的类定义;
    public class FeedBack : MulticastDelegate
    {
    //构造器
    public FeedBack(Object target, Int32 methodPtr);
    //下面的方法和源代码中指定的原型相同
    public void virtual Invoke(Object value, Int32 item; Int32 numItems);
    //下面两个方法允许我们对委托进行异步回调
    public virtual IAsyncResult BeginInvoke(Object value, Int32 item; Int32 numItems ,AsyncCallback callback, Object object);
    public virtual void EndInvoke(IAsyncResult result);
    }
    我们只关注构造器和Invoke方法。
    构造器方法中的target存放的是方法对象的引用,如App.FeedBackToFile中的App,methodPtr存放的是一个特殊的标志方法的Int32值。这些就可以准确的标识一个方法。Invoke方法会被自动调用。
  • 相关阅读:
    华为为什么再发布2016年就已经对外露脸甚至商用的欧拉操作系统。
    更安全,仅允许当前用户运行脚本法:vscode运行python时提示无法加载文件xxx.venvScriptsactivate.ps1
    ubuntu下安装odoo 14.0框架
    安利: Swagger工具, 一个REST APIs文档生成工具
    关注Brython 项目,在浏览器中运行python,部分替代javascript
    2021年最火的前端框架
    2021 最受欢迎的前端 八 个 UI 框架
    取代os.path的模块pathlib
    Java中Int转byte分析
    基于Java的时间转换:Date、Timestamp和String时间转化
  • 原文地址:https://www.cnblogs.com/xxaxx/p/2072073.html
Copyright © 2011-2022 走看看