一、delegate
基础
1、基本简介
- 委托是一种类型,该类型可以赋值一个函数的引用。即,委托是把一个函数当作参数来进行传递。其作用类似于
C++
中的函数指针,是一种函数指针的升级版,类似于自己不做,委托给别人来做的情况。 - 它是和类(
class
)具有同等地位的,所以其声明一般是位于命名空间namespace
下、且位于类外部。(委托也可以声明在类的内部,此时其相当于类的嵌套类型。如同在一个类的内部,声明另一个类一样) - 委托和类的用法相同,都是需要先声明,再实例化,只是实例化之后仍然叫委托。(委托虽然也为引用类型,但是其实例化并不是一定要用
new
操作符,如作为一个函数的形参时,可以直接创建,无需new
) - 委托是不可变的,委托一旦创建好就无法更改。
- 委托的声明和函数的声明类似,只是前面多了关键字
delegate
,且委托没有函数体。 - 其用法是将函数名作为参数来进行传递,让委托的对象指向该函数。
- 委托的返回值和形参列表必须要与被引用的函数相同。
- 委托通过
=
或+=
来将函数注册(也称引用)到委托的实例上,使用-=
来将函数注销。
2、示例
(1)、委托在使用前需要先进行声明,其结构为:访问修饰符 关键字delegate
返回值类型 委托类型名(形参列表)。
(2)、委托使用
namespace Pr01_Basic
{
class Program
{
static void Main(string[] args)
{
A obj = new A();
//委托实例化,用函数AddNum来对其进行实例化,此时委托相当于对该函数的引用。
TheDege dg = new TheDege(obj.AddNum);
dg(20); //此时相当于调用 obj.AddNum(20)函数
// 或者使用如下方式实例化委托:
TheDege dg2;
dg2 = obj.AddNum;
Console.ReadKey();
}
}
// 声明委托
public delegate void TheDege(int num);
class A
{
public void AddNum(int num)
{
Console.WriteLine("Call the AddNum = {0}.", num + 10);
}
public void SubNum(int num)
{
Console.WriteLine("Call the SubNum = {0}.", num - 10);
}
}
}
二、多播委托
1、多播委托简介
- 多播委托是同一个委托可以对多个函数进行引用,即可以同时调用多个函数。具体是通过
+=
符号来进行增加连接,通过-=
符号减少连接。 - 在调用时,将按照函数的引用顺序来依次进行调用。
- 多播委托的返回值为
void
类型,由于此时委托引用了多个函数,如果有返回值的话,将不知道该返回哪个引用函数的值了。
2、示例
namespace Pr01_Basic
{
class Program
{
static void Main(string[] args)
{
A obj = new A();
TheDege dg = new TheDege(obj.AddNum); //用AddNum来实例化委托
dg += new TheDege(obj.SubNum); //将SubNum函数加入到委托中,该委托将同时引用两个函数
dg(20); //此时相当于同时调用AddNum和SubNum函数
Console.WriteLine();
dg -= new TheDege(obj.AddNum); //此时AddNum函数将从该委托中被删除,该委托指引用SubNum函数
dg(20);//此时相当于调用SubNum函数
Console.ReadKey();
}
}
// 声明委托
public delegate void TheDege(int num);
class A
{
public void AddNum(int num)
{
Console.WriteLine("Call the AddNum = {0}.", num + 10);
}
public void SubNum(int num)
{
Console.WriteLine("Call the SubNum = {0}.", num - 10);
}
}
}
三、Action
和 Func
委托
除了自定义的委托类型外,系统还为我们提供了内置的委托类型,Action
和 Func
委托。这两者均为泛型
1、Action
委托
Action
委托引用了一个 void
返回类型的方法。即,Action
只能指向一个没有返回值的函数(Action
位于 System
命名空间下)
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace ATotal
{
class Program
{
static void PrintValue01() // 无返回值,无参
{
Console.WriteLine("This is PrintValue01");
}
static void PrintValue02(int a) // 无返回值,有参
{
Console.WriteLine("a = " + a);
}
static void Main(string[] args)
{
Action ac01 = PrintValue01; // 指向有参数的函数
Action<int> ac02 = PrintValue02; // 指向无参数的函数
ac01();
ac02(10);
Console.ReadKey();
}
}
}
2、Func
委托
Func
委托引用了一个带有返回值的函数(该委托必须有一个返回值)。它可以传递 0 − 16 0 -16 0−16 个参数和一个返回值。Func
有多个参数,其中最后一个为返回值类型,前面的为所指向的函数参数类型,它们必须和指向函数的参数保持一致。
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace ATotal
{
class Program
{
static int PrintValue01()
{
return 100;
}
static int PrintValue02(float a)
{
Console.WriteLine("a = " + a);
return 666;
}
static void Main(string[] args)
{
// 在此使用了泛型int,表示函数返回值类型
Func<int> fun01 = PrintValue01;
Console.WriteLine(fun01());
// Func 中间可以有多个类型,其中最后一个参数为返回值类型,前面的都是参数类型
Func<float, int> fun02 = PrintValue02;
Console.WriteLine(fun02(88));
Console.ReadKey();
}
}
}
参考资料:
1、C# 中的委托和事件(详解)