Learning CLR via C#(3)
- CLR要求将接口方法标记为virtual,如果源代码中没有显示地将方法标记为virtual,编译器会将它们标记为virtual和sealed,这会阻止派生类重写接口方法。
- 一个类型加载到CLR中时,会为该类型创建并初始化一个方法表。在这个方法表中,类型引入的每个新方法都有一条对应的记录项;另外,还为该类型继承的所有虚方法添加了记录项。
- 可以用显示接口方法实现(EIMI)来增强编译时的类型安全性:
internal struct SomeValueType : IComparable { private int _value; public SomeValueType(int value) { _value = value; } public int CompareTo(SomeValueType other) { return _value - other._value; } int IComparable.CompareTo(object other) { return CompareTo((SomeValueType)other); } }
-
CLR将所有多维数组都视为非0基数组。访问一维0基数组的元素比访问非0基一维数组或多维数组稍快一些。
-
垃圾回收:
public void Test() { Timer t = new Timer(TimerCallBack, null, 0, 2000); Console.ReadLine(); } private void TimerCallBack(object state) { Console.WriteLine("In TimerCallBack: " + DateTime.Now.ToString()); GC.Collect(); }Timer只会执行一次。
public void Test() { using (Timer t = new Timer(TimerCallBack, null, 0, 2000)) { Console.ReadLine(); } }可以正确多次执行。
- 如果一个类型定义了Finalize方法,那么在该类型的实例构造器被调用之前,会将指向该对象的一个指针放到一个终结列表中。当垃圾回收开始时,垃圾回收器会扫描终结列表查找垃圾对象的指针,如果找到,该指针会从终结列表中移除,并追加到freachable列表中。一个特殊的高优先级CLR线程专门负责调用Finalize方法。加到freachable中的指针指向的对象不会被回收内存直到Finalize方法被调用。
- GC中新创建的对象属于第0代,在对第0代回收中存活下来的对象提升为第1代,对第1代回收中存活下来的对象提升为第2代。代越高分配的内存预算就越大,回收频率越低。
- 跨AppDomain通信的方式:1.按引用封送(继承MarshalByRefObject)。2.按值封送(可序列化)。
- 对于带有ref,out等参数的反射调用:
internal sealed class SomeType { public void RefMethod(ref int a) { a += 3; } }可以使用
typeof(int).MakeByRefType()或
Type.GetType("System.Int32&")来获得参数Type信息。
public void Test() { object[] args = new object[] { 12 }; Type t = typeof(SomeType); MethodInfo method = t.GetMethod("RefMethod", new[] { typeof(int).MakeByRefType() }); method.Invoke(new SomeType(), args); Console.WriteLine(args[0]); method = t.GetMethod("RefMethod", new[] { Type.GetType("System.Int32&") }); method.Invoke(new SomeType(), args); Console.WriteLine(args[0]); }out和ref的调用方式完全一样,因为两者在IL层面是没有区别的。