1、嵌套类,就是定义在类中的类;嵌套类可以访问外部类的方法、属性、字段而不管访问修饰符的限制,但是外部类只能够访问修饰符为public、internal的嵌套类的字段、方法、属性;
2、CLR如何调用虚方法、属性和事件:
IL提供两个方法调用指令:call和callvirt。
call调用静态方法、实例方法和虚方法;callvirt调用实例方法和虚方法,不能调用静态方法;
call关心的是编译时类型;callvirt关心的是运行时类型;所以,用callvirt调用虚方法时,CLR要调查发生调用的对象的实际类型,为了确定类型,发生调用的变量绝不能是null。
如有两个类:
internal class Person{ }
internal class Employee:Person{ }
void main(){
Person p=new Employee();//p在编译时的类型是Person,而在运行时的类型是Employee
}
call不会检测对象是否为null。而callvirt会检测。所以callvirt指令的执行速度比call指令稍慢。
3、C#用callvirt指令调用所有实例方法。
但是编辑器有时用call而不是callvirt调用虚方法。虽然刚开始有点难以理解,但是以下证明了有时需要这样做:
internal class SomeClass{
//ToString是基类Object定义的虚方法
public override String ToString(){
//编译器使用IL指令'call'
//以非虚方式调用Object的ToString方法
//如果编辑器用'callvirt'而不是'call',
//那么该方法将递归调用自身,直至栈溢出(但是为什么会递归调用自身呢,这里不是base吗,是基类吗?)
return base.ToString();
//我的理解:这里实际和reutrn this.ToString()没区别,因为base虽然是基类指针,但是用callvirt时,会检测实际类型,而实际类型就是自身,所有会无限递归调用自身的方法。(不知识这样理解对不对)
}
}