zoukankan      html  css  js  c++  java
  • C#引用类型和值类型的区别(转)

    转载自百度文库仅做学习之用,转载地址:http://wenku.baidu.com/view/261864c48bd63186bcebbcdb.html

        我们都知道,c#的两大数据类型分别为值类型和引用类型。很多人或许闭着眼睛都能说出 值类型包括简单类型、结构体类型和枚举类型,引用类型包括自定义类、数组、接口、委托 等,但是当被问及到二者之间的联系和区别,什么时候用 struct 什么时候用 class 时,就常 常混淆不清了。为此,了解值类型和引用类型的本质差异就变的很有必要了。

         1、值类型直接存储其值,变量本身就包含了其实例数据,而引用类型保存的只是实例数据 的内存引用。因此,一个值类型变量就永远不会影响到其他的值类型变量,而两个引用类型 变量则很有可能指向同一地址,从而发生相互影响。

         2、从内存分配上来看,值类型通常分配在线程的堆栈上,作用域结束时,所占空间自行释 放,效率高,无需进行地址转换,而引用类型通常分配在托管堆上,由 GC 来控制其回收, 需要进行地址转换,效率降低,这也正是 c#需要定义两种数据类型的原因之一。 

         3、 值类型均隐式派生自 System.ValueType,而 System.ValueType 又直接派生于 System.Object,每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值, 注意所 有的值类型都是密封(sealed)的,所以无法派生出新的值类型。而且 System.ValueType 本身是一个类类型,而不是值类型,因为它重写了 object 的 Equals()方法,所以对值类型 将按照实例的值来比较,而不是比较引用地址。

         4、C# 的统一类型系统,使得值类型可以转化为对象来处理,这就是常说的装箱和拆箱。 由于装拆箱需要装建全新对象或做强制类型转换, 这些操作所需时间和运算要远远大于赋值 操作,因此不提倡使用它,同时也要尽量避免隐式装拆箱的发生。

        注:栈是操作系统分配的一个连续的内存区域,用于快速访问数据。因为值类型的容量是已 知的,因此它可存储在栈上。而托管堆是 CLR 在应用程序启动时为应用程序预留的一块连 续内存区,是用于动态内存分配的内存区,引用类型的容量只有到运行时才能确定,所有用 堆来存储引用类型。

        C#的两种数据类型延伸之一--嵌套类型的内存分配 对于引用类型嵌套值类型,以及值类型嵌套引用类型的情况下,内存分配可以根据以下 两条规律来判断:

        1、 引用类型始终部署在托管堆上;

        2、值类型总是分配在它声明的地方:作为字段时,跟随其所属的对象存储;作为局部变量 时,存储在 栈上。

        C#的两种数据类型延伸之二--string 类型 string 是一个很有意思的引用类型, 为什么说它很有意思呢?因为它表现了很多值类型的 特点。

    请看一下代码示例:

       示例

            1 string str1 = "abc"; string str2 = str1; str1 = "123"; Console.WriteLine(str2);

       示例

          2(msdn 上的例子) string a = "hello"; string b = "h"; // Append to contents of 'b' b += "ello"; Console.WriteLine(a == b);

        示例 1 的输出结果是 abc,改变 str1 的值对 str2 没有影响。 示例 2 的输出结果是 True。 这样的结果会使我们误以为 string 就是值类型。其实不然,示例 1 中 str1 = "123"语句编 译器私底下创建了一个新的字符串对象来保存新的字符序列"123",也就是此 str1 已非彼 str1 了,“此”str1 的值的改变也就不能影响“彼”str1 的值了,当然 str2 的值也就不会改变了。 实质上 str1 = "123"是 str1=new string("123")的简写,它的每一次赋值都会抛掉原来的对象 而生成一个新的字符串对象,分配新的内存空间,因此 string 是不可改变的。如果要创建可 修改的字符串, 可使用 stringbuilder 以获得更好的性能。 至于示例 2 是因为为了方便比较字 符串的值重定义了 string 的运算符== 和 !=。

        C#的两种数据类型延伸之三--struct 和 class class 和 struct 的语法基本相同, 从声明到使用, 都很相似。 但是 struct 的约束要比 class 多,理论上,struct 能做到的 class 都能做到,但 class 能做到的 stuct 却不一定做的到,也 就是说 struct 都能被 class 所代替。 那么为什么还要使用 struct 呢?存在即是合理的, struct 在很多方面有着性能优势。让我们看看它们的主要区别在哪里?

        1、 数据类型不一样,struct 是值类型,class 是引用类型,因此它们具有所有值类型和 引用类型之间的差异。由于堆栈的执行效率要比堆的执行效率高,但是堆栈资源却 很有限,不适合处理逻辑复杂的大对象,因此 struct 常用来处理作为基类型对待的 小对象,而 class 来处理某个商业逻辑。 从继承性来看,struct 既不能继承也不能被继承,但是可以实现接口,而 Class 就 可以完全扩展了。 内部结构有区别,struct 只能添加带参的构造函数,不能使用 abstract 和 protected 等修饰符, 不能初始化实例字段, 但是值得注意的是, struct 可以重写 System.Object 的 3 个虚方法,Equals()、ToString()和 GetHashTable(),Class 没有这些限制。 比较 struct 和 class 的不同,可以得出以下几条 struct 和 class 的使用原则: 1 在表示诸如点、矩形等主要用来存储数据的轻量级对象时,首选 struct。 2 在表示数据量大、逻辑复杂的大对象时,首选 class。 3 在表现抽象和多级别的对象层次时,class 是最佳选择

  • 相关阅读:
    Ruby on rails3新手谈(1):Ruby on rails环境搭建
    更灵活,更易维护的WebHandler之通用webHandler编码方案(2)
    .Net Remoting之windows服务部署
    Ruby on rails3新手谈(2):简单的例子helloworld
    分组取最新记录的SQL
    验证日期的Javascript
    使用Javascript创建遮罩层并模拟Alert、Confirm对话框
    取得当前鼠标的X,Y坐标,及相关属性的介绍
    B/S结构系统中使用Session遇到的问题
    IE与FireFox的兼容性问题
  • 原文地址:https://www.cnblogs.com/zyhblogs/p/2719518.html
Copyright © 2011-2022 走看看