这篇文章之前发布在我的个人博客上了,http://www.vsmvp.com/Post.aspx?id=13
学习Jeffrey Richter的CLR via C#已经有两个月的时间,每天早上起床看一个小时,目前也就看到了14章。发现看到后面前面的内容基本上就差不多忘记了,所以打算写个类似读书笔记的东西,记下干货方便自己日后查阅。可能有人不知道CLR via C#这本书名是什么意思,根据我这几个月的理解,应该是通过C#了解CLR的意思。
言归正传,CLR支持两种类型,值类型和引用类型。下图是MSDN对值类型和引用类型的经典描述
- 引用类型的内存必须从托管堆上分配
- 堆上分配的每个对象都有一些额外的成员【额外成员包括一些同步索引块、对象指针等必须的东西】,这些成员必须初始化
- 对象中的其他字节总是零
- 从托管堆上分配一个对象实例时,可能强制执行一次垃圾回收
public static void Go() {
SomeRef r1 = new SomeRef(); // Allocated in heap
SomeVal v1 = new SomeVal(); // Allocated on stack
r1.x = 5; // Pointer dereference
v1.x = 5; // Changed on stack
Console.WriteLine(r1.x); // Displays "5"
Console.WriteLine(v1.x); // Also displays "5"
// The left side of Figure 5-2 reflects the situation
// after the lines above have executed.
SomeRef r2 = r1; // Copies reference (pointer) only
SomeVal v2 = v1; // Allocate on stack & copies members
r1.x = 8; // Changes r1.x and r2.x
v1.x = 9; // Changes v1.x, not v2.x
Console.WriteLine(r1.x); // Displays "8"
Console.WriteLine(r2.x); // Displays "8"
Console.WriteLine(v1.x); // Displays "9"
Console.WriteLine(v2.x); // Displays "5"
// The right side of Figure 5-2 reflects the situation
// after ALL the lines above have executed.
}
- 类型不需要从其他类型中继承
- 类型不需要被其他类型继承
- 类型的实例字段不会给成员更改【建议将值类型的字段都设置为readonly】
- 类型的实例比较小。16字节或这一下
- 类型的实例比较大,但是不作为方法的实参传递,也不从方法返回。
- 值类型对象的两种表示形式:未装箱和装箱。对值类型的装箱操作是非常消耗性能的。
- 值类型不能被其他类型(包括值类型和引用类型)继承。所以值类型里面不可以有新的虚方法,方法不能是抽象的,都必须是密闭的。
- 值类型总是有默认值,不能为null
- 将一个值类型的变量赋给另一个值类型的变量是,会执行一次逐个字段的赋值。而引用类型的变量赋给另一个引用类型的变量时,只复制内存地址
- 基于上一条,值类型的变量值不会受到另一个值类型变量的影响。应用类型如果同时指向同一个托管堆,那么任何一个引用变量的改变都会影响其他的变量。
- 线程栈上的值类型,实例不可达时便会给自动释放,所以不会收到Finalize的通知。
- 在托管堆中分配好内存。【这里分配的内存总理是值类型各个字段需要的内存量加上托管堆上对象都有的额外成员(类型对象指针和同步索引块)需要的内存量】
- 值类型的字段复制到新分配的托管堆内存中
- 返回现分配的托管堆上对象的地址。值类型现在是一个引用类型了。
· 从任何 value-type 到 object 类型。
· 从任何 value-type 到 System.ValueType 类型。
· 从任何 non-nullable-value-type 到 value-type 实现的任何 interface-type。
· 从任何 nullable-type 到由 nullable-type 的基础类型实现的任何 interface-type。
· 从任何 enum-type 到 System.Enum 类型。
· 从任何具有基础 enum-type 的 nullable-type 到 System.Enum 类型。
取消装箱转换允许将 reference-type 显式转换为 value-type。存在以下拆箱转换:
· 从 object 类型到任何 value-type。
· 从 System.ValueType 类型到任何 value-type。
· 从任何 interface-type 到实现了该 interface-type 的任何 non-nullable-value-type。
· 从任何 interface-type 到其基础类型实现了该 interface-type 的任何 nullable-type。
· 从 System.Enum 类型到任何 enum-type。
· 从 System.Enum 类型到任何具有基础 enum-type 的 nullable-type。
public static void Main6() {
Int32 v = 5;
Object o = v;
v = 123;
Console.WriteLine(v + ", " + (Int32)o);
}