(一)委托/函数指针的意义
C#中的委托本质上相当于是像C/C++的函数指针。
如果我们只从调用结果上看,我们会发现,委托和直接调用函数之间的区别是很小的。
using System; //一般的写法 namespace Test1 { class Program { static void Main(string[] args) { Console.WriteLine("Hello world"); } } }
using System; //基于委托的写法 namespace Test1 { class Program { static void Main(string[] args) { Action ation = new Action(Program2.OutPut); ation(); } } class Program2 { public static void OutPut() { Console.WriteLine("Hello world"); } } }
那么既然这样,C#中的委托的价值在哪里?
我个人认为应该主要有三个。
其一,对于一些常用并且封装度比较高的方法,我们在调用时,可以通过委托的方式来对它进行一个绑定,调用时可以更加的便捷
其二,作为泛型使用。
其三,委托可以实现回调函数。这里简述一下。
当我们通过指针作为形参调用一个类型时,我们到底在做什么?
我们把形参指针b绑定在a上,看上去好像都是在操作底层的那一段地址上存储的数据
但是,这里还有一个区别就是,我们是在通过以一个其他的东西来为媒介,不直接通过main函数里面的那个数据来操作地址上的一段数据。
//一般的操作 int a=100; void Test(){ std::cout<<a<<std::endl; } int main(void){ Test(); }
//使用指针操作 void Test(int* b){ //do something std::cout<<*b<<std::endl; } int main(void) { int a=100; Test(&a); }
在这时,我们考虑一个问题:
如果我们想要改变Test里面的输出内容,对于以上的两段代码该如何操作?
如果我们不用指针。我们需要改变在Test()函数体里面直接调用的全局变量。我们会发现,这样的写法会造成一个问题,就是对于复杂的系统中,该代码的耦合度会非常高。
而当我们使用指针进行处理的时候,由于函数的形参的指针和调用函数入口处的指针本身时分离开的,当我们只需要改变函数调用时的实参即可。
通过以上的论述其实对于委托(函数指针)的作用我们也差不多可以明白了。
#include<iostream> int(*vis)(int, int); int Sum(int a,int b){ return a+b; } int Test(int a,int b,int(*visit)(int,int)){ return visit(a,b); } int main(void){ vis=Sum; std::cout<<Test(100,200,vis); system("pause"); }
以C++为例,就像以上,我们只需要改变vis的指向,或者更直接的,改变Test调用的实参,就可以改变这个逻辑相同的函数函数调用而不用深入函数体内部进行过多的修改从而成功的降低耦合。
(二)委托的声明形式
首先我们需要明白,在C#之中的委托是一种类型(也许在上面的声明过程中你已经发现了)
其次,我们须知,我们一般会将委托声明为命名空间的下一级,即与一般的类型相同的级别而不是声明为符合类型。
再次,微软已经为我们准备两个类模板。
//微软的类模板 //Action //Action代表一类默认没有返回值的类模板,其共有0——16个参数重载 using System; namespace Test1 { class Program { static void Main(string[] args) { Program2 p1=new Program2(); Action<int,int> a1=new Action<int, int>(p1.OutPut); Action<int> a2=new Action<int>(p1.OutPut2); a1(1,2); a2(1); } } class Program2 { public void OutPut(int a,int b) { Console.WriteLine("Hello world"); } private void OutPut2(int a) { ; } } } //Func //Func代表的是一种有返回值的泛型委托。 //Func<int>代表无参,返回值为int的委托 //Func<object,string,int>代表传入值为object和string,返回值时int的委托 //Func<T1,T2,T3....Return>代表传入值为T1,T2.....为传入值,Return是返回值的泛型委托 //Func至少1个参数,至多16个参数,必须有返回值不可为void Func<> ;//会报错,错误内容: "message": "使用泛型 类型“Func<TResult>”需要 1 个类型参数 [c#]" //Predicate //Predicate的返回类型固定为bool,却只有一种泛型委托必须有且只有一个参数
//自己定义的委托 using System; namespace Test1 { public delegate void De(int a,int b); class Program { static void Main(string[] args) { Program2 p2=new Program2(); De de=new De(p2.OutPut); de(1,2); } } class Program2 { public void OutPut(int a,int b) { Console.WriteLine("Hello world"); } } } //我们要记住,委托是一种类型 public delegate void De(int a,int b) //声明的是返回值为void 参数列表为int和int的委托类型
以上就是委托的基本使用