值类型与引用类型
作为托管语言C#,我们不得不了解其数据类型,包括内存分配,内存回收,此乃底层调优之必备。
CLR支持两种类型:引用类型和值类型。虽然FCL的大多数都是引用类型,但程序员用得最多的还是值类型。引用类型总是从托管堆分配,C#的new操作符返回对象内存地址---即指向对象数据的内存地址。使用引用类型必须注意性能问题。首先要认清楚以下四个事实:
- 内存必须从托管堆分配。
- 堆上分配的每个对象都有一些额外成员,这些成员必须初始化。
- 对象中的其他字节(为字段而设)总是设为0。
- 从托管堆分配对象时,可能强制执行一次垃圾回收。
试想,如果所有类型都是引用类型,那么应用程序的性能将显著下降。设想每次使用Int32值时都进行一次内存分配,性能会受到多么大的影响!为了提升简单和常用的类型性能,CLR提供了“值类型”的轻量级类型。值类型的实例一般在线程栈上分配,不受垃圾回收器的控制。因此,值类型的使用缓解了托管堆的压力,并减少了应用程序生存期内的垃圾回收次数。
任何称为“类”的类型都是引用类型。如:System.Exception类、System.IO.FileStream类及System.Random等都是引用类型。反之,所有值类型都称为结构或者枚举。例如
System.Int32结构、System.Boolean结构、System.Decimal结构、System.TimeSpan结构、System.DayOfWeek枚举、System.Drawing.FontStyle枚举等。
代码演示:
- 声明一个引用类型的类Class
1 /// <summary> 2 /// 引用类型 3 /// </summary> 4 class SomeRef 5 { 6 public int Age { get; set; } 7 }
2.再声明一个值类型的结构struct
1 /// <summary> 2 /// 结构为值类型 3 /// </summary> 4 struct SomeVal 5 { 6 public int Age { get; set; } 7 }
3.通过控制台操作并打印结果,代码如下:
static void Main(string[] args) { SomeRef r1 = new SomeRef(); //引用类型在堆上分配空间 SomeVal v1 = new SomeVal(); //在栈上分配 r1.Age = 16; //提领指针 v1.Age = 16; //在栈上修改 Console.WriteLine(r1.Age); // 显示 “16” Console.WriteLine(v1.Age); // 同样显示"16" //下图 的左半部分反映了执行以上代码之后的情况 SomeRef r2 = r1; //只复制引用(指针) SomeVal v2 = v1; //在栈上分配并复制成员 r1.Age = 18; //r1.Age 和r2.Age都会发生变化 v1.Age = 19; //v1.Age会改,v2.Age不会改 Console.WriteLine(r1.Age); //18 Console.WriteLine(r2.Age); //18 Console.WriteLine(v1.Age); //19 Console.WriteLine(v2.Age); // 16 //下图右半部分反映执行以上所有代码后的情况 Console.ReadKey(); }
4.如下图说明:

以上是对值类型与引用类型的理解,如有错误,欢迎指正!!!

浙公网安备 33010602011771号