1. 值类型 C#的所有值类型均隐式派生自System.ValueType: · 结构体:struct(直接派生于System.ValueType); · 数值类型: · 整型:sbyte(System.SByte的别名),short(System.Int16),int(System.Int32),long(System.Int64),byte(System.Byte),ushort(System.UInt16),uint(System.UInt32),ulong(System.UInt64),char(System.Char); · 浮点型:float(System.Single),double(System.Double); · 用于财务计算的高精度decimal型:decimal(System.Decimal)。 · bool型:bool(System.Boolean的别名); · 用户定义的结构体(派生于System.ValueType)。 · 枚举:enum(派生于System.Enum); · 可空类型(派生于System.Nullable<T>泛型结构体,T?实际上是System.Nullable<T>的别名)。 每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。例如:
等价于:
等价于:
等价于:
使用new运算符时,将调用特定类型的默认构造函数并对变量赋以默认值。在上例中,默认构造函数将值0赋给了i。 所有的值类型都是密封(seal)的,所以无法派生出新的值类型。 值得注意的是,System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。 可以用Type.IsValueType属性来判断一个类型是否为值类型: - TestType testType = new TestType ();
- if (testTypetype.GetType().IsValueType)
- {
- Console.WriteLine("{0} is value type.", testType.ToString());
- }
复制代码
2. 引用类型 C#有以下一些引用类型: · 数组(派生于System.Array) · 用户用定义的以下类型: · 类:class(派生于System.Object); · 接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题。) · 委托:delegate(派生于System.Delegate)。 · object(System.Object的别名); · 字符串:string(System.String的别名)。 可以看出: · 引用类型与值类型相同的是,结构体也可以实现接口; · 引用类型可以派生出新的类型,而值类型不能; · 引用类型可以包含null值,值类型不能(可空类型功能允许将 null 赋给值类型); · 引用类型变量的赋值只复制对对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值。 对于最后一条,经常混淆的是string。例如: - string s1 = "Hello, ";
- string s2 = "world!";
- string s3 = s1 + s2;//s3 is "Hello, world!"
复制代码这确实看起来像一个值类型的赋值。再如: - string s1 = "a";
- string s2 = s1;
- s1 = "b";//s2 is still "a"
复制代码改变s1的值对s2没有影响。这更使string看起来像值类型。实际上,这是运算符重载的结果,当s1被改变时,.NET在托管堆上为s1重新分配了内存。这样的目的,是为了将做为引用类型的string实现为通常语义下的字符串。
|