从CLR和编译器合作的角度看,C#委托类型是如何被构造和调用的?请描述其底层实现机制。
考察说明
考查对C#委托底层机制的理解,包括类型结构、编译器生成和调用原理。
回答思路
- 【回答框架 1】委托在C#中本质是一个类,由编译器生成,继承自MulticastDelegate,包含构造函数和Invoke等核心方法。它封装了方法引用和可选的目标对象,支持多播。
- 【回答框架 2】编译器将委托声明编译为类,并为每个委托类型生成Invoke、BeginInvoke、EndInvoke等方法,这些方法基于目标方法指针实现。创建委托时,会通过newobj指令构造实例,传入方法地址和实例。
- 【回答框架 3】调用委托时,Invoke方法会被直接调用,内部通过Delegate类型的InvokeMethod方法或直接调用目标方法指针(如calli指令)来执行。对于多播委托,内部维护一个调用列表,依次调用所有绑定的方法。
- 【回答框架 4】底层依赖CLR的委托机制,包括方法指针、目标对象和调用列表。CLR提供了特殊支持,如防止伪造委托、确保类型安全,以及处理静态方法和实例方法的统一调用约定。
- 【关键点 1】委托是继承自MulticastDelegate的密封类,由编译器生成。
- 【关键点 2】每个委托类型包含Invoke、BeginInvoke、EndInvoke等方法,封装方法指针和实例。
- 【关键点 3】委托调用通过Invoke或calli指令,多播委托内部维护方法调用列表。
- 【易错点 1】不能将委托直接等同于函数指针,因为委托是类型安全的对象,还包含多播支持和异步调用等能力。
- 【易错点 2】不要混淆委托的Invoke和动态调用(DynamicInvoke),显式调用Invoke性能更好,不使用反射。
- 【易错点 3】多播委托的调用顺序是同步顺序,如果某个方法抛出异常,后续方法将不会执行。