本文重点
- delegate 和 Delegate 的区别 
- 定义委托 
- 实例化委托 
- Action 和 Func 
- 委托的基本用法 
delegate
delegate 是一个类型关键字, 和它类似的还有: class, interface, enum 等等. 这类关键字都是用来定义的, 而不是实例化的. 枚举类型使用 enum 进行定义, 委托类型使用 delegate 进行定义. 因此 delegate 不是类! 它只是一个类型关键字! 用来定义类型的.
System.String - string 和 System.Delegate - delegate
System.String 是 .Net 框架中的一个类, .Net 框架中包含多种编程语言, 其中 C# 语言中给 System.String 起了一个别名 string, 因此 string str 和 System.String str 是没有区别的, string 就是一个类, string str 这一个代码不是在定义类型, 而是在实例化对象. 但是 delegate 和 System.Delegate 的关系就不是这样了. System.Delegate 是一个类, 而 delegate 则是一个 类型关键字, 它是用来定义委托的, 就像 class 定义类, struct 定义结构体, enum 定义枚举一样, 这些关键字是同一个级次的, 但他们都不是类.
如下图, String, string, Delegate 都可以调用类中的静态方法, 这是因为他们都是类, 但是 delegate 则不可以, 因为它仅仅只是一个类型关键字.
![delegate]()
🦄如何定义一个委托类型
- 使用 delegate 关键字
- 指明待委托方法的两个特征: 1. 返回值 2. 参数
| 12
 
 | public delegate int MyDelegate (int a, int b);
 
 | 
[注] 其实 csharp 中已经有定义好的通用委托类型了, 基本无需自己定义委托类型.
🐬如何实例化出一个委托实例
实例化委托就是使用之前定义好的委托类型实例化出一个委托对象, 也叫做委托实例. 委托的实例化语法和类的实例化语法相同.
[注] 实例化委托时通常不再使用自己定义的委托类型, 而是使用 csharp 中已经定义好的通用委托类型 Action<> 和 Func<>.
🌴如何初始化一个委托实例
[注] 待委托方法如果不是静态方法, 则必须是实例方法. 不能将未实例化的方法作为参数传入委托或对委托赋值.
如何调用委托
- 方式 1: 调用委托和调用方法在代码写法上一致.
- 方式 2: 调用 Invoke() 方法.
委托基本用法示例 (非静态)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 
 | using System;using System.Collections.Generic;
 
 
 
 
 namespace MyDelegateTest
 {
 
 using Package = Dictionary<string, int>;
 
 
 public delegate string DelegateBuy(string itemName, int num, Package package);
 
 class Program
 {
 public static void Main()
 {
 
 Package package = new Package();
 
 
 
 
 Program program = new Program();
 DelegateBuy delegateBuy = program.Buy;
 DelegateBuy delegateBuy2 = new DelegateBuy(program.Buy);
 
 
 Console.WriteLine(delegateBuy("体力药水", 10, package));
 Console.WriteLine(delegateBuy("体力药水", 25, package));
 Console.WriteLine(delegateBuy2("魔力药水", 10, package));
 Console.WriteLine(delegateBuy2("魔力药水", 5, package));
 
 
 Console.ReadKey();
 }
 
 
 
 
 
 
 
 public string Buy(string itemName, int num, Dictionary<string, int> package)
 {
 string str;
 
 if (package.ContainsKey(itemName))
 {
 package[itemName] += num;
 str = string.Format("您又购买了{0}个{1}!", num, itemName);
 }
 else
 {
 package.Add(itemName, num);
 str = string.Format("您购买了{0}个{1}!", num, itemName);
 }
 
 return str;
 }
 }
 }
 
 | 
委托基本用法示例 (静态)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 
 | using System;using System.Collections.Generic;
 
 
 
 
 namespace MyDelegateTest
 {
 
 using Package = Dictionary<string, int>;
 
 
 public delegate string DelegateBuy(string itemName, int num, Package package);
 
 class Program
 {
 public static void Main()
 {
 
 Package package = new Package();
 
 
 
 DelegateBuy delegateBuy = Program.Buy;
 DelegateBuy delegateBuy2 = new DelegateBuy(Program.Buy);
 
 
 Console.WriteLine(delegateBuy("体力药水", 10, package));
 Console.WriteLine(delegateBuy("体力药水", 25, package));
 Console.WriteLine(delegateBuy2("魔力药水", 10, package));
 Console.WriteLine(delegateBuy2("魔力药水", 5, package));
 
 
 Console.ReadKey();
 }
 
 
 
 
 
 
 
 public static string Buy(string itemName, int num, Dictionary<string, int> package)
 {
 string str;
 
 if (package.ContainsKey(itemName))
 {
 package[itemName] += num;
 str = string.Format("您又购买了{0}个{1}!", num, itemName);
 }
 else
 {
 package.Add(itemName, num);
 str = string.Format("您购买了{0}个{1}!", num, itemName);
 }
 
 return str;
 }
 }
 }
 
 | 
Action 和 Func
在实例化委托的时候, 不仅仅可以使用自己定义的委托, 还可以使用 csharp 中已经定义好的两个泛型委托: Action<> 和 Func<> 来实例化 (强烈建议使用).
Action
Action<> 待委托的方法都是没有返回值的方法, 参数使用泛型进行指定.
| 12
 3
 
 | Action a; Action<string> b;
 Action<string, int[]> c;
 
 | 
Func
Func<> 待委托的方法都是具有返回值的方法. 使用泛型来指定参数和返回值. 其中泛型中的最后一个类型为返回值的类型.
| 12
 3
 
 | Func<string> a; Func<string, int> b;
 Func<int, string, int[]> c;
 
 | 
总结
- delegate 和 Delegate 的区别: -  Delegate 是类, delegate 是关键字. 
- 定义委托 -  不再自定义委托, 使用 Action<> 和 Func<>. 
- 实例化委托 -  使用泛型指明待委托方法的特征. 
- Action 和 Func -  Action<> 指明无返回值, Func<> 最后一个泛型类型指明返回值. 
- 委托的基本用法 -  可以通过委托来调用方法. 
参考链接
理解委托类型