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方法会被自动调用。
  • 相关阅读:
    'Undefined symbols for architecture i386,clang: error: linker command failed with exit code 1
    The codesign tool requires there only be one 解决办法
    XCode iOS project only shows “My Mac 64bit” but not simulator or device
    Provisioning profile XXXX can't be found 的解决办法
    UIView 中的控件事件穿透 Passthrough 的实现
    Xcode4.5出现时的OC新语法
    xcode 快捷键(持续更新)
    打越狱包
    php缓存与加速分析与汇总
    浏览器的判断
  • 原文地址:https://www.cnblogs.com/xxaxx/p/2072073.html
Copyright © 2011-2022 走看看