Table of Contents

C#中的委托

委托是一种引用类型,表示对具有特定参数列表返回类型方法的引用

对函数特征的匹配要求并不是完全严格的:方法不必与委托类型完全匹配

感觉像函数指针?官方文档:委托类似于 C++ 函数指针,但委托完全面向对象,不像 C++ 指针会记住函数,委托会同时封装对象实例和方法。

函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用

可以用来实现多态,想想和C++虚函数有什么关系吗

对比事件


声明一个委托类型

delegate <return type> <delegate-name> <parameter list>;
 
public delegate void printString(string s); // 声明委托,表明了能绑定的函数的特征,包括返回值
// 看起来像是函数声明,但应该是声明了一个“类型”,这个类型描述了和其匹配的函数的要求
// printString变成了一个像类型名一样的东西

实例化一个委托

<delegate-name> <instance-name> = new <delegate-name>(<function-name>);
 
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile); // 就好像一个变量绑定了一个函数

使用委托

ps1("Hi"); // 把变量像函数一样使用
printString ps3 = ps1; // 变量还方便传递
 
// 委托也可以使用Invoke进行触发

多播

NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc = nc1;
nc += nc2; // 将两个委托合并起来
nc(5); // 调用多播

静态和非静态函数

namespace Zhonghui
{ 
    class MainApp
    {
        private string m_kName;
 
        public MainApp(string Name)
        {
            m_kName = Name;
        }
 
        // 非静态函数,可以访问this
        private void ASay(string Text)
        {
            Console.WriteLine(this.m_kName + "'s A:" + Text);
        }
 
        private void BSay(string Text)
        {
            Console.WriteLine(this.m_kName + "'s B:" + Text);
        }
 
        // 静态函数
        public static void StaticSay(string Text)
        {
            Console.WriteLine("Static Say:" + Text);
        }
 
        public delegate void Say(string Text);
 
        static void Main()
        {
            var MainA = new MainApp(new string("Apple"));
            var MainB = new MainApp(new string("Banana"));
 
            // 绑定非静态函数:Object.Function
            // 委托是和这个具体对象关联的
            var A = new Say(MainA.ASay); // Apple的A函数
            var B = new Say(MainB.BSay); // Banana的B函数
 
            // 绑定静态函数:Class.Function
            var AB = A + B + new Say(MainApp.StaticSay); // 同时调用3个函数
 
            A("I am A");
            B("I am B");
            AB("We are A & B");
        }
    }
}

通用委托

首先:“通用委托”是我自己起的名字,指的是Action,Func和Predicate

这些东西是为了干啥呢?首先,声明委托像是声明一个类型,委托不同也就是其匹配的参数列表和返回值不同,所以,其实不用为了使用一次委托而单独声明一种类型,使用通用的就可以了

演示一下:

namespace Zhonghui
{ 
    class MainApp
    {
        static void Main()
        {
            // Action匹配类型:可以有参数(也可以没有),不能有返回值
            var P = new Action<string>(Print);
 
            // Func匹配类型:可以有参数(也可以没有),必须有返回值
            // <>里面最后一个是返回值类型,前面写参数类型列表
            var A = new Func<float, float, int>(Add);
 
            // Predicate匹配类型:有且只有一个参数,返回值必须为bool
            var I = new Predicate<int>(IsZero);
 
            // 调用都是和普通委托一样
            P("Action");
            Console.WriteLine(A(1, 2));
            Console.WriteLine(I(0));
        }
 
        // 有参数,没有返回值
        static void Print(string Text)
        {
            Console.WriteLine(Text);
        }
 
        // 有参数,也有返回值
        static int Add(float x,float y)
        {
            return (int)(x + y);
        }
 
        // 只有一个参数,返回值是bool
        static bool IsZero(int x)
        {
            return (x == 0);
        }
    }
}