.Net的类型系统叫公共类型系统(Common Type System,CTS)。公共类型系统是一种简单的类型系统,像上面类型分类中那些复杂的类型在.Net中就很难找到对应物(也许F#能,哥低头看地板,反正那些类型指啥俺都不知道),玩类型的人都跑去玩haskell了。在他们看来,.Net的类型系统 too simple, too naive。
下图是MSDN描述的公共类型系统的类型体系结构:

我翻译一下:

值类型和引用类型是.Net的最基本的两类类型。下面是MSDN上对值类型和引用类型的解释:
Value types directly contain their data, and instances of value types are either allocated on the stack or allocated inline in a structure. Value types can be built-in (implemented by the runtime), user-defined, or enumerations. For a list of built-in value types, see the .NET Framework Class Library.
Reference types store a reference to the value's memory address, and are allocated on the heap. Reference types can be self-describing types, pointer types, or interface types. The type of a reference type can be determined from values of self-describing types. Self-describing types are further split into arrays and class types. The class types are user-defined classes, boxed value types, and delegates.
从这上面可以看出,值类型和引用类型代表着两类约束:
(1)值类型包含自己的数据,值类型分配在栈上或者内联于其它结构体(structure,非struct!)之中;
(2)引用类型存储的是到堆上数据的一个引用(这句话不完全准确,指针也可以指向栈上的数据)。
这样一来,区分值类型和引用类型就很直接了。
type t = tValue,这里的t如果包含它的数据,则type为值类型,如果t只包含引用,具体取值还要根据内存去查找的话,则就是引用类型。
类型不一定非要有自己的数据。比如接口类型,它所指向的数据就是类类型的数据或者值类型装箱为类类型后的数据。指针类型,它所指向的数据是值类型的数据。
下面是争论比较大的。
(1)指针类型。
int* p = xxx。根据上面的判断方式,int*是引用类型。
(2)接口类型
IInterface i = (IInterface)Entity。这里的i也只是一个引用,如果Entity是class,则指向该class在堆上的地址,如果Entity是struct,则指向该struct装箱之后,在堆上的地址。
(3)class和.class之辩
.Net中,万物都是.class,这是实现层面,而关键字class则是类型层面的,它代表“类类型”。