当前位置:嗨网首页>书籍在线阅读

11-高手点拨

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

3.5 高手点拨

**本节视频教学录像:4分钟**

引用类型和值类型变量的使用是C#中的高级技巧之一。值类型变量中保存的是自己的实际数据,在赋值的时候会把源变量的数据复制一份,然后赋给目的变量;引用类型变量中保存的是“指向实际数据的指针”,即实际对象数据的内存地址,在进行赋值操作的时候,它和值类型一样,也是先有一个复制的操作,不过它复制的不是实际的数据,而是引用(真实数据的内存地址)。

1.怎么区分值类型与引用类型

以struct关键字定义的数据类型就是值类型,另外,枚举类型也是值类型;以class关键字定义的数据类型就是引用类型。

2.值类型变量与引用类型变量的使用区别

值类型变量不需要使用new关键字来分配内存。相信大家使用int型变量时,就没有使用new来为其分配内存,定义完之后,就可以直接使用;引用类型变量则需要为其赋值后,才能使用。下面举例说明值类型与引用类型在使用上的区别。

首先定义两种类型的员工:结构体SEmployee和类CEmployee。

01  struct SEmployee
02  {
03           public int Age; 
04  }
05  class CEmployee
06  {
07           public int Age;
08  }

在main函数中,按照如下编写:

01  {
02    SEmployee se;
03    se.Age = 4;
04    Console.WriteLine("年龄:{0}", se.Age);
05    Console.ReadKey();
06  }

程序编译没有任何问题,运行后输出【年龄:4】。现在按照如下的代码编写main函数:

01  {
02    CEmployee ce;
03    ce = new CEmployee();
04    ce.Age = 5;
05    Console.WriteLine("年龄:{0}", ce.Age);
06    Console.ReadKey();
07  }

这时程序就不能通过编译,提示使用了未赋值的变量“ce”,把注释掉的那一行恢复就可以顺利通过编译,运行后输出【年龄:5】 。

通过这个小例子可以看出,值类型变量在定义后,就直接可以使用,而引用类型必须使用new关键字后才能使用。对于引用类型会有“未将对象引用设置到对象的实例”错误,而值类型不会发生这种错误。

3.值类型与引用类型的内存分配区别

内存分配时间:值类型变量在定义后就完成内存分配,引用类型必须显式用new关键字来分配内存。

内存分配区域:值类型的实例一般在线程栈上分配(也可以作为字段嵌入引用类型的对象中),在代表值类型的变量中,并不包含一个指向实例的指针,变量已经包含了实例本身的字段;引用类型总是从托管堆分配的,C#的new操作符会返回对象的内存地址,也就是指向对象数据的内存地址。

4.值类型与引用类型的优缺点

值类型变量在定义后,不论使用与否都会进行内存分配,因此当定义值类型而又没有使用的情况下,这些无用的变量就白白占用了内存。

值类型是按值传递的,也就是当用一个变量给另外一个变量赋值时,会把源变量的值赋值一遍,传给目的变量,当值类型(结构体)定义的比较大时,值类型的传递效率就非常低。

每个值类型的变量都有自己的内存空间,很难做到几个值类型的变量共享一个内存空间。

引用类型变量在定义后,不会自动分配内存,因此我们可以在用到引用类型变量的时候,用new来分配空间,不会造成内存的浪费;但是,引用类型是在托管堆上分配的,也就是其内存回收通过垃圾回收器来回收,引用类型的使用会增加应用程序在其生存期内需要进行的垃圾回收次数。

引用类型是按引用传递的,也就是内存地址在引用类型变量之间传递,这种传递方式效率非常高,当对象非常大时,可以优先考虑引用类型。

每个引用变量存储的是内存地址,可以实现多个变量共享一个内存空间。

当数据传递后,要求对目的变量的修改不能影响源变量的值,可以考虑将数据类型设计为值类型;当数据可以传递后,要求其后的操作必须影响到源数据,可以考虑将数据类型设计为引用类型。值类型与引用类型各有优缺点,使用时应根据实际的需要,选择合适的类型。