黑马程序员技术交流社区

标题: 值类型和引用类型 [打印本页]

作者: 穷傻呆丑萌    时间: 2013-8-31 19:21
标题: 值类型和引用类型

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

1.

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

2.

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

3.

值类型均隐式派生自
System.ValueType


System.ValueType
又直接派生于
System.Object,
每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值,注意所有的值类型都是密封

sealed
)的,所以无法派生出新的值类型。而且
System.ValueType
本身是一个类类型,而不
是值类型,因为它重写了
object

Equals()
方法,所以对值类型将按照实例的值来比较,而不是
比较引用地址。

4.

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

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



C#
的两种数据类型延伸之一
--
嵌套类型的内存分配


对于引用类型嵌套值类型,以及值类型嵌套引用类型的情况下,内存分配可以根据以下两条规律来判
断:


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






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



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
在很多方面有着性能优势。让我们看看它们的主要区别在哪里?



数据类型不一样,
struct
是值类型,
class
是引用类型,因此它们具有所有值类型
和引用类型之间的差异。由于堆栈的执行效率要比堆的执行效率高,但是堆栈资源
却很有限,
不适合处理逻辑复杂的大对象,
因此
struct
常用来处理作为基类型对待
的小对象,而
class
来处理某个商业逻辑。



从继承性来看,
struct
既不能继承也不能被继承,但是可以实现接口,而
Class

可以完全扩展了。



内部结构有区别,
struct
只能添加带参的构造函数,不能使用
abstract

protec
ted
等修饰符,
不能初始化实例字段,
但是值得注意的是,
struct
可以重写
System.
Object

3
个虚方法,
Equals()

ToString()

GetHashTable()

Class
没有这些
限制。

比较
struct

class
的不同,可以得出以下几条
struct

class
的使用原则:

1
在表示诸如点、矩形等主要用来存储数据的轻量级对象时,首选
struct


2
在表示数据量大、逻辑复杂的大对象时,首选
class


3
在表现抽象和多级别的对象层次时,
class
是最佳选择



作者: ℡跡....    时间: 2013-8-31 22:27
学习了。。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2