DoNet:浅淡对delegate的理解

1 前言

C#的相关文档,MSDN上其实已经很详细了,关于delegate的使用可以参
考MSDN上的文档https://msdn.microsoft.com/zh-cn/library/900fyy8e.aspx

2 官方示例

委托类型的声明与方法签名相似, 有一个返回值和任意数目任意类型的参数:

public delegate void TestDelegate(string message);
public delegate int TestDelegate(MyType m, long num);

delegate 是一种可用于封装命名或匿名方法的引用类型。 委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。 有关委托的应用,请参见委托和泛型委托。

备注
委托是事件的基础。通过将委托与命名方法或匿名方法关联,可以实例化委托。 有关更多信息,请参见命名方法和匿名方法。必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。 有关方法签名中允许的差异程度的更多信息,请参见委托中的变体(C# 和 Visual Basic)。 为了与匿名方法一起使用,委托和与之关联的代码必须一起声明。 本节讨论这两种实例化委托的方法。

C#示例

// Declare delegate -- defines required signature:
delegate double MathAction(double num);

class DelegateTest
{
    // Regular method that matches signature:
    static double Double(double input)
    {
        return input * 2;
    }
    static void Main()
    {
        // Instantiate delegate with named method:
        MathAction ma = Double;

        // Invoke delegate ma:
        double multByTwo = ma(4.5);
        Console.WriteLine("multByTwo: {0}", multByTwo);

        // Instantiate delegate with anonymous method:
        MathAction ma2 = delegate(double input)
        {
            return input * input;
        };

        double square = ma2(5);
        Console.WriteLine("square: {0}", square);

        // Instantiate delegate with lambda expression
        MathAction ma3 = s => s * s * s;
        double cube = ma3(4.375);

        Console.WriteLine("cube: {0}", cube);
    }
    // Output:
    // multByTwo: 9
    // square: 25
    // cube: 83.740234375
    }

3 个人见解

3.1 C语言函数指针

以下代码简单实现了C语言中的函数指针

#include <iostream>
using namespace std;

//this is likely to "delegate"
typedef void(*func)(void);

//this is likely to "event"
func event;

void CallBack()
{
    cout << "Callback start running" << endl;   
}

int main()
{
    event= CallBack;
    event();
}

一、typedef void(*func)(void); 定义了一个返回为void,传入参数为void的函数指针类型,类似于C#中的delegate;
二、func enent; 定义了一个名为event的函数指针变量;
三、主函数中将回调函数CallBack的地址赋值给event这个变量,event();即执行回调函数 CallBack()

运行结果

这里写图片描述

3.2 C#个人示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CsharpCallback
{

    class Program
    {
        public delegate void Handler(int i);
        public event Handler EventRegister;
        void CallBack(int i)
        {
            Console.WriteLine("Callback is running " + i);
        }   
        void CallTest(int i)
        {
            Console.WriteLine("Calltest is running " + i);
        }
        void RegisetCallback()
        {
            EventRegister += new Handler(CallBack);
            EventRegister += new Handler(CallTest);                 
        }     
        static void Main(string[] args)
        {
            Program test = new Program();
            test.RegisetCallback();
            for (int i=0; i<100; i++)
            {
                if(i == 50)
                {
                    test.EventRegister(i);
                }
            }          
        }
    }
}

程序分析:
一、 public delegate void Handler(int i); 这里申明了一个名为Handler 委托,当然类似于C中的函数指针,可以参考C代码的示例加以理解,同样的,对于回调函数类型需要和委托相同;
二、public event Handler EventRegister; 这里我理解为定义了一个函数指针的变量(这个理解可能欠妥当),event的具体使用,可以参考官方文档https://msdn.microsoft.com/zh-cn/library/8627sbea.aspx
三、RegisetCallback() 函数则将回调函数的指针赋值给指针变量。
程序运行结果:
这里写图片描述

4 总结

粗浅的认识了一下C#中的delegate和event的简单用法,并将其与C++中的函数指针做了对比,发现存在相似之处,event的详细使用可以在MSDN上参考官方文档,这方面做的很不错,由于作者水平和能力有限,文中必有错误或者不恰当处,请各位多多指教

原文地址:https://www.cnblogs.com/unclemac/p/12783449.html