如果enum定义中没有显式地指定基础类型,c#编译器就将假定基础类型是System.Int32。你可以使用下面的语法重写这个默认设置。
[System.Flags]
Public enum Organs:btye{
None=0x00,
Hear=0x01,
Lung=0x02,
Liver=0x04,
Kidney=0x08
}
这个示例将每个字面值的基础类型声明为system.Byte。尽符枚举的成员名必须惟一,但对于每个成员的整型值却设有这种惟一性要求。事实上,使用枚举类型表示位掩码(bitmask)是能用的方式。为了使这种用法更为明确,枚举可以应用[System.Flags]特性。这个特性向开发人员表明了其预期的用法。它还将影响底层的ToString实现,这样枚举值的字符串化版本将会是逗号分隔的成员名的列表,而不是个数字。
变量、参数和字段
引用类型总是会产生分配在堆上的实例。相比之下,对于值类型产生的实例。 它的分配与变量声明的上下文相关。如果一个局部变量是值类型,CLR将在堆栈上分配该实例的内存;如果一个类中的某个字段是值类犁的成员,CLR将为实例分配内存,井将其作为声明该字段的对象或类型的布局的一部分。对于变量、字段和参数而言,用于处碑值类型和引用类型的规则是一致的。为此,本章将使用术语变量( variable)代表达三个概念。当计论变量本身的时候将使用术语局部变量(Local variable)。
引用类型变量(reference type variable)如同其名字的含义:它包含对象引用而不是它们声明的类型实例;引用类型只是包含它所引用的对象地址。这意味着两个引用类型变量可能引用同一个对象。此外,对于一个对象引用来说,根本不指向任何对象也是可能的。在使用一个引用变量之前,必须首先将它初始化,使其指向一个有效对象。如果你试图通过一个没有指向有效对象的引用来访问其成员,就会导致运行时错误。引用类型字段的默认值为null(空),这是一个不指向任何对象的地址。任何使用空引用的尝试都将导致System.NullReferenceException异常。有趣的是,你可以大胆地假设你所使用的任何对象引用都会指向一个有效对象或者nu11,因为使用一个未经初始化的引用,要么会被编译器捕获,要么就被CLR验证器捕获,此外,如果你有一个存活的变量或字段在引用对象,那么CLR将不会释放这个对象。
引用类型变量总是需要一个对象。相反,值类型变量(value type variable)自身就是实例,而不是引用。这意味着,值类型变量一旦声明就立即有效。
示例5.1是这两个类型的例子:一个是引用类型,另一个是值类型,除此之外,其他都是一样的。这里,变量v能够被立即使用,因为其实例己经被作为变量声明的一部分而分配,相比之下,变量r不能被立即使用,需要等它指向堆上的有效对象后才可用。图5.3展示了两个变量在内存中是如何分配的。
示例5.1 使用值类型和引用类型
public struct Size{
public int height;
public int weight;
}
public sealed class CSize{
public int height;
public int weight;
}
Static App{
static void Main(){
size v; //v是size的一个实例
v.height=100; //合格
CSize r; //r是一个引用
r.height=100; //非法,r是悬挂的(dangling)
r=new CSize(); //r引用Cdize的一个实例
r.height=100; //合法,r不再悬挂
}
}
e