值类型与引用类型

   作为托管语言C#,我们不得不了解其数据类型,包括内存分配,内存回收,此乃底层调优之必备。

  CLR支持两种类型:引用类型和值类型。虽然FCL的大多数都是引用类型,但程序员用得最多的还是值类型。引用类型总是从托管堆分配,C#的new操作符返回对象内存地址---即指向对象数据的内存地址。使用引用类型必须注意性能问题。首先要认清楚以下四个事实:

  1. 内存必须从托管堆分配。
  2. 堆上分配的每个对象都有一些额外成员,这些成员必须初始化。
  3. 对象中的其他字节(为字段而设)总是设为0。
  4. 从托管堆分配对象时,可能强制执行一次垃圾回收。

   试想,如果所有类型都是引用类型,那么应用程序的性能将显著下降。设想每次使用Int32值时都进行一次内存分配,性能会受到多么大的影响!为了提升简单和常用的类型性能,CLR提供了“值类型”的轻量级类型。值类型的实例一般在线程栈上分配,不受垃圾回收器的控制。因此,值类型的使用缓解了托管堆的压力,并减少了应用程序生存期内的垃圾回收次数。 

   任何称为“类”的类型都是引用类型。如:System.Exception类、System.IO.FileStream类及System.Random等都是引用类型。反之,所有值类型都称为结构或者枚举。例如

System.Int32结构、System.Boolean结构、System.Decimal结构、System.TimeSpan结构、System.DayOfWeek枚举、System.Drawing.FontStyle枚举等。

  代码演示:

  1.  声明一个引用类型的类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.如下图说明:

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

posted @ 2017-03-14 17:38  〆海浔、深蓝(小武)  阅读(162)  评论(0)    收藏  举报