C# 值类型和引用类型
2011-08-16 23:31 DylanChan 阅读(272) 评论(0) 编辑 收藏 举报◆值类型直接存储其值,变量本身就包含了其实例数据,而引用类型保存的只是实例数据的内存引用。因此,一个值类型变量就永远不会影响到其他的值类型变量,而两个引用类型变量则很有可能指向同一地址,从而发生相互影响。
◆从内存分配上来看,值类型通常分配在线程的堆栈(Sack)上,作用域结束时,所占空间自行释放,效率高,无需进行地址转换,而引用类型通常分配在托管堆(Heap)上,由GC来控制其回收,需要进行地址转换,效率降低,这也正是c#需要定义两种数据类型的原因之一。
◆值类型均隐式派生自System.ValueType,而System.ValueType又直接派生于System.Object,每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值,注意所有的值类型都是密封(sealed)的,所以无法派生出新的值类型。而且System.ValueType本身是一个类类型,而不是值类型,因为它重写了object的Equals()方法,所以对值类型将按照实例的值来比较,而不是比较引用地址。
◆C# 的统一类型系统,使得值类型可以转化为对象来处理,这就是常说的装箱和拆箱。由于装拆箱需要装建全新对象或做强制类型转换,这些操作所需时间和运算要远远大于赋值操作,因此不提倡使用它,同时也要尽量避免隐式装拆箱的发生。
栈是操作系统分配的一个连续的内存区域,用于快速访问数据。因为值类型的容量是已知的,因此它可存储在栈上。
托管堆是CLR在应用程序启动时为应用程序预留的一块连续内存区,是用于动态内存分配的内存区,引用类型的容量只有到运行时才能确定,所有用堆来存储引用类型。
string类型
class Program { static void Main() { string str1 = "abc"; string str2 = str1; str1 = "123"; Console.WriteLine(str2); //输出结果是abc,改变str1的值对str2没有影响。 string a = "hello"; string b = "h"; // Append to contents of 'b' b += "ello"; Console.WriteLine(a == b); //输出结果是True } }
class和struct的语法基本相同,从声明到使用,都很相似。但是struct的约束要比class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不一定做的到,也就是说struct都能被class所代替。那么为什么还要使用struct呢?存在即是合理的,struct在很多方面有着性能优势。让我们看看它们的主要区别在哪里?
struct AStruct { int aField; } class AClass { int aField; } class MainClass { public static void Main() { AClass b = null; // No error. AStruct s = null; // Error [ Cannot convert null to 'AStruct' because it is a value type ]. } }
class MyClass { int myVar = 10; // no syntax error. } struct MyStruct { int myVar = 10; // 结构中不能有实例字段初始值设定项 }
class MyClass { int myVar = 10; public MyClass() // no syntax error. { // statements } } struct MyStruct { int myVar; public MyStruct() //结构不能包含显式的无参数构造函数 { // statements } }
class Program { static void Main() { MyClass mc = new MyClass(); //类使用前必须new关键字实例化 Console.WriteLine(mc.myVar); MyStruct ms; ms.myVar = 100; } } class MyClass { public int myVar = 10; } struct MyStruct { public int myVar; }
class MyClass { int myInt; string myString; public MyClass(int aInt) { //Statement } } struct MyStruct { public int myInt; public string myString; public MyStruct(int aInt) { myInt = 3; myString = "abc"; } }