黑马程序员技术交流社区

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

作者: 特洛伊    时间: 2013-10-31 23:50
标题: 值类型和引用类型的区别
本帖最后由 特洛伊 于 2013-11-2 12:27 编辑

什么是值类型? 什么是引用类型 ?他们什么区别?

作者: 蒋东东    时间: 2013-11-1 00:10
值类型直接存储其值,而引用类型存储对其值的引用;值类型是在栈中操作,而引用类型则在堆中分配存储单元;值类型存取速度快,引用类型存取速度慢。
作者: nooooy    时间: 2013-11-1 00:21
C#的值类型:一种由类型的实际值表示的数据类型 。包括:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型。
C#的引用类型: 由类型的实际值引用(类似于指针)表示的数据类型。 包括:数组,用户定义的类、接口、委托,object,字符串。
区别:
1. 将一个值类型变量赋值给另一个值类型变量时,将复制变量包含的值;引用类型的变量的赋值是只复制对对象的引用,而不复制对象本身
2. 值类型不可能派生出新的类型,所有的值类型均隐式的派生自System,ValueType。但与引用类型相同的是结构体也可以实现接口。
3. 值类型不可能包含空值null,但引用类型可以为空。
4. 每种值类型都有一个隐式的默认的构造函数来初始化该类型的变量

作者: 一羽丶轻舟    时间: 2013-11-1 08:27
C#值类型数据直接在他自身分配到的内存中存储数据,而C#引用类型只是包含指向存储数据位置的指针。
基础数据类型(string类型除外):包括整型、浮点型、十进制型、布尔型。整型包括:sbyte、byte、char、short、ushort、int、uint、long、ulong 这九种类型;浮点型就包括 float 和 double 两种类型;十进制型就decimal ;布尔型就是 bool 型了。结构类型:就是 struct 型。枚举类型:就是 enum 型。引用类型有五种:class、interface、delegate、object、string引用类型作为参数时:
1、在修改变量本身时,结果类似于值传递,即不会改变传递前的变量的值
2、在修改变量的属性或字段时,才是引用传递,会影响到传递前的变量的值
3、参数使用了ref后,才是真正的引用传递,不管修改变量本身还是修改变量的属性或字段,都会影响到传递前的变量的值值传递:传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)
引用传递:传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)在Java中:
1. 基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。
   2. 对象和引用型变量被当作参数传递给方法时,是引用传递。在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。和c#中的一样,只不过Java中没有ref, out等关键字
作者: 吴彤辉    时间: 2013-11-1 09:34
1. 值类型
C#的所有值类型均隐式派生自System.ValueType:
· 结构体:struct(直接派生于System.ValueType);
· 数值类型:
· 整型:sbyte(System.SByte的别名),short(System.Int16),int(System.Int32),long(System.Int64),byte(System.Byte),ushort(System.UInt16),uint(System.UInt32),ulong(System.UInt64),char(System.Char);
· 浮点型:float(System.Single),double(System.Double);
· 用于财务计算的高精度decimal型:decimal(System.Decimal)。
· bool型:bool(System.Boolean的别名);
· 用户定义的结构体(派生于System.ValueType)。
· 枚举:enum(派生于System.Enum);
· 可空类型(派生于System.Nullable<T>泛型结构体,T?实际上是System.Nullable<T>的别名)。
每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。例如:
  1. int i = new int();
复制代码

等价于:
  1. Int32 i = new Int32();
复制代码

等价于:
  1. int i = 0;
复制代码

等价于:
  1. Int32 i = 0;
复制代码

使用new运算符时,将调用特定类型的默认构造函数并对变量赋以默认值。在上例中,默认构造函数将值0赋给了i。
所有的值类型都是密封(seal)的,所以无法派生出新的值类型。
值得注意的是,System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。
可以用Type.IsValueType属性来判断一个类型是否为值类型:
  1. TestType testType = new TestType ();
  2. if (testTypetype.GetType().IsValueType)
  3. {
  4.      Console.WriteLine("{0} is value type.", testType.ToString());
  5. }
复制代码

2. 引用类型
C#有以下一些引用类型:
· 数组(派生于System.Array)
· 用户用定义的以下类型:
· 类:class(派生于System.Object);
· 接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题。)
· 委托:delegate(派生于System.Delegate)。
· object(System.Object的别名);
· 字符串:string(System.String的别名)。
可以看出:
· 引用类型与值类型相同的是,结构体也可以实现接口;
· 引用类型可以派生出新的类型,而值类型不能;
· 引用类型可以包含null值,值类型不能(可空类型功能允许将 null 赋给值类型);
· 引用类型变量的赋值只复制对对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值。
对于最后一条,经常混淆的是string。例如:
  1. string s1 = "Hello, ";
  2. string s2 = "world!";
  3. string s3 = s1 + s2;//s3 is "Hello, world!"
复制代码
这确实看起来像一个值类型的赋值。再如:
  1. string s1 = "a";
  2. string s2 = s1;
  3. s1 = "b";//s2 is still "a"
复制代码
改变s1的值对s2没有影响。这更使string看起来像值类型。实际上,这是运算符重载的结果,当s1被改变时,.NET在托管堆上为s1重新分配了内存。这样的目的,是为了将做为引用类型的string实现为通常语义下的字符串。



作者: 追溯客    时间: 2013-11-2 10:51
如果问题得到解决,请及时将分类设为"已解决",这样各位版主才方便给你加分哦!




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