本文重点
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 关键字
- 指明待委托方法的两个特征:
1. 返回值 2. 参数
1 2
| public delegate int MyDelegate (int a, int b);
|
[注] 其实 csharp 中已经有定义好的通用委托类型了, 基本无需自己定义委托类型.
🐬如何实例化出一个委托实例
实例化委托就是使用之前定义好的委托类型实例化出一个委托对象, 也叫做委托实例. 委托的实例化语法和类的实例化语法相同.
[注] 实例化委托时通常不再使用自己定义的委托类型, 而是使用 csharp 中已经定义好的通用委托类型 Action<> 和 Func<>.
🌴如何初始化一个委托实例
[注] 待委托方法如果不是静态方法, 则必须是实例方法. 不能将未实例化的方法作为参数传入委托或对委托赋值.
如何调用委托
- 方式 1: 调用委托和调用方法在代码写法上一致.
- 方式 2: 调用 Invoke() 方法.
委托基本用法示例 (非静态)
1 2 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; } } }
|
委托基本用法示例 (静态)
1 2 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<> 待委托的方法都是没有返回值的方法, 参数使用泛型进行指定.
1 2 3
| Action a; Action<string> b; Action<string, int[]> c;
|
Func
Func<> 待委托的方法都是具有返回值的方法. 使用泛型来指定参数和返回值. 其中泛型中的最后一个类型为返回值的类型.
1 2 3
| Func<string> a; Func<string, int> b; Func<int, string, int[]> c;
|
总结
delegate 和 Delegate 的区别:
Delegate 是类, delegate 是关键字.
定义委托
不再自定义委托, 使用 Action<> 和 Func<>.
实例化委托
使用泛型指明待委托方法的特征.
Action 和 Func
Action<> 指明无返回值, Func<> 最后一个泛型类型指明返回值.
委托的基本用法
可以通过委托来调用方法.
参考链接
理解委托类型