第三节:C#数据类型
C#中的数据类型根据其定义可以分成两种:值类型和引用类型。区别在于数据的存储方式。
值类型的变量本身直接存储数据,而引用类型则存储实际数据的引用,程序通过引用找到真实数据。
整型
C#内置的,独特的数据类型有:
byte(8位无符号数) 表示0~255
sbyte(8位有符号数) 表示-128~127
而在Python中,byte表示字节,注意区分。
浮点型
如果不做任何设置,包含小数点数值都被认定为double型,这一点同C++。如果要将浮点数强行按照float 类型来处理,就应当通过在数值后加f或F将其转换为float型。否则,不同于C/C++的警告,C#会直接抛出错误。如图所示:
decimal型
decimal 型是C#提供的一种精度更高的浮点型。包含128位,精度可以达到28位,因此可以用来做财务和货币计算。如果一个小数被当成decimal,需要使用后缀m或M。
引用类型
引用类型是构建C#应用程序的主要对象类型数据。在应用程序执行的过程中,预先定义的对象类型以new创建对象实例,并且存储在堆中。拥有以下特征:
- 必须在托管堆中为引用类型变量分配内存。
- 使用new关键字来创建引用类型变量。
- 托管堆中分配的每个对象都有与之关联的附加成员,这些对象必须被初始化。
- 引用类变量由C#自带的垃圾回收机制管理。
- 引用类被赋值前值都是null。
- 多个引用类变量可以引用同一对象,此时对一个变量操作会影响另一个变量引用的同一对象。
关于第六点,如下所示:
可以看出,r1和r2绑定在同一个对象上。所以尽管r1的Value并未初始化,改变r2的Value也改变了r1的Value值。
值与引用的区别
从内存空间上看,值类型在栈上操作,而引用型在堆内分配。栈在编译时就分配好了内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间。因此,值类型总是在内存中的占用一个预定义的字节数,而引用型变量则在堆中分配一个内存空间,这个空间包含的是对另一个内存空间的引用,这个位置是托管堆中的一个地址,即存放变量实际值的地方。
类型转换
除了常规的显式和隐式转换外,C#还可以通过Convert关键字进行显式转换。
上面提到了值类型和引用类型,这两者也是可以互相转换的。将值转引用称为装箱,反之称为拆箱。
装箱允许将值类型隐式转换为引用类型:
从结果中可以看出,值类型变量值复制到装箱得到的对象中,装箱后改变值变量值时,不会影响装箱对象值。
拆箱后得到的值类型数据值与装箱对象相等,而在拆箱时要注意符合类型一致原则,否则会出现异常。如不能将一个值为string类型的object型对象转换为int型。
事实上,C#的object型是所有类型的最高级父类,所有类型无论是用户自定义还是系统定义都派生自object型,所有类型都可以向上转换为object类型。而装拆箱特性赋予了C#更强的灵活性。
更新于2022.3.28下午