3.6 类型转换
知识点讲解:光盘:视频\PPT讲解(知识点)\第3章\类型转换.mp4
在计算机中,所有的数据都是由0和1构成的。C#中最简单的类型是char,它可以用一个数字表示Unicode字符集中的一个字符。在默认情况下,不同类型的变量使用不同的方式来表示数据。这意味着在变量值经过移位处理后,所得到的结果将会不同。为此,就需要类型转换来解决上述问题。C#中的类型转换有隐式转换和显式转换两种,本节将详细讲解这两种类型转换的基本知识。
3.6.1 隐式转换
隐式转换是系统的默认转换方式,即不需要特别声明即可在所有情况下进行。在进行C#隐式转换时,编译器不需要进行检查就能进行安全的转换处理。C#的隐式转换一般不会失败,也不会导致信息丢失。例如,下面的代码使变量值从int类型隐式地转换为了long类型。
int mm=20;
long nn=mm;
在C#中,允许对简单类型变量进行隐式转换,但是其中的bool和string类型变量是不能被隐式转换的。编译器可以隐式执行的数值转换类型如表3-5所示。
表3-5 C#中可隐式转换的数值类型列表
类 型 |
可转换的类型 |
---|---|
byte |
short、ushort、uint、int、ulong、long、float、double、decimal |
sbyte |
short、int、long、float、double、decimal |
short |
int、long、double、decimal |
ushort |
uint、int、ulong、long、float、double、decimal |
int |
long、float、double、decimal |
uint |
ulong、long、float、double、decimal |
long |
float、double、decimal |
ulong |
float、double、decimal |
float |
double |
char |
ushort、uint、int、ulong、long、float、double、decimal |
3.6.2 显式转换
顾名思义,显式转换是一种强制性的转换方式。在使用显式转换时,必须在代码中明确地声明要转换的类型。这就意味着需要编写特定的额外代码,并且代码的格式会随着转换方式的不同而不同。
虽然C#允许变量进行显式转换,但需要注意下面两点。
- 隐式转换是显式转换的一种特例,所以允许将隐式转换书写成显式转换的格式。
- 显示转换并不安全,因为不同类型的变量取值范围是不同的,所以如果强制执行显示转换,则可能会造成数据的丢失。
C#显式转换的语法格式如下。
类型 变量名=(类型)变量名
可从下面的2段代码中看出显式转换和隐式转换的区别。隐式转换的代码如下。
int mm=20;
long nn=mm; //隐式转换
显式转换的代码如下。
int mm=20;
long nn=(long)mm; //显式转换
显式转换是从一个数值类型向另一个数值类型进行转换的过程,由于显式转换包括隐式转换,所以总能将表达式从任何数值类型强制转换为其他任何类型,虽然在转换过程中会出现数据丢失。
编译器可显式转换的数值类型如表3-6所示。
表3-6 C#可显式转换的数值类型列表
类 型 |
可转换的类型 |
---|---|
byte |
sbyte、char |
sbyte |
byte、ushort、uint、ulong、char |
short |
sbyte、byte、ushort、uint、ulong、long、char |
ushort |
sbyte、byte、short、char |
int |
sbyte、byte、short、ushort、uint、ulong、char |
uint |
sbyte、byte、short、ushort、int、char |
long |
sbyte、byte、short、ushort、uint、int、ulong、char |
ulong |
sbyte、byte、short、ushort、uint、int、long、char |
float |
sbyte、byte、short、ushort、uint、int、ulong、long、char、float |
char |
sbyte、byte、short |
decimal |
sbyte、byte、short、ushort、uint、int、ulong、long、char、float、double |
double |
sbyte、byte、short、ushort、uint、int、ulong、long、char、float、decimal |
3.6.3 装箱与拆箱
C#中的值类型和引用类型在实质上讲是同源的,所以不但可以在值类型与值类型之间、引用类型与引用类型之间进行转换,也可以在值类型和引用类型之间进行转换。但是由于两者使用的内存类型不同,使它们之间的转换变得比较复杂。在C#中,通常将值类型转换为引用类型的过程称为装箱,将引用类型转换为值类型的过程称为拆箱。
装箱和拆箱是整个C#类型系统的核心模块,在值类型和引用类型之间架起了一座桥梁。最终使任何值类型的值都可以转换为object类型值,object类型值也可以转换为任何类型的值,并把类型值作为一个对象来处理。
下面对装箱与拆箱的基本知识进行简要介绍。
1.装箱
装箱允许将值类型转换为引用类型,转换规则如下。
- 从任何的值类型到类型object的转换。
- 从任何的值类型到类型System.ValueType的转换。
- 从任何的值类型到值类型的接口转换。
- 从任何枚举类型到类型System.Enum的转换。
在C#中,将一个值类型装箱为一个引用类型的过程如下。
(1)在托管堆中创建一个新的对象实例,并分配对应的内存。
(2)将值类型变量值复制到对象实例中。
(3)将对象实例地址复制到堆栈中,并指向一个引用类型。
实例002 演示C#装箱操作的实现过程
源码路径 光盘\daima\3\2\ 视频路径 光盘\视频\实例\第3章\002
实例文件Zhuangxiang.cs的实现代码如下。
namespace Zhuangxiang
{
class Program
{
public static void Main()
{
int mm = 50; // 定义值类型变量
object nn = mm; // 将值类型变量值装箱到引用类型对象
Console.WriteLine("值为{0},装箱对象为{1}", mm, nn);
mm = 100; // 改变值
Console.WriteLine("值为{0},装箱对象为{1}", mm, nn);
Console.ReadKey();
}
}
}
范例003:泛型委托和Lamdba实现计算器
源码路径:光盘\演练范例\003视频路径:光盘\演练范例\003范例004:整型数组排序
源码路径:光盘\演练范例\004视频路径:光盘\演练范例\004\
在上述实例代码中,首先定义了变量mm的数值类型为int,且初始值为50;然后对mm的值进行装箱处理为对象nn,具体过程如下。
- 将变量mm的值50进行装箱,转换为对象nn。
- 将变量mm的值修改为100,然后进行装箱,转换为对象nn。
经过“csc /out:zhuangxiang.exe zhuangxiang.cs”命令编译处理后,程序执行结果如图3-6所示。
图3-6 实例执行结果
2.拆箱
拆箱允许将引用类型转换为值类型,具体说明如下。
- 从类型object到任何值类型的转换。
- 从类型System.ValueType到任何值类型的转换。
- 从任何的接口类型到对应的任何值类型的转换。
- 从类型System.Enum到任何枚举类型的转换。
在C#中,将一个值类型拆箱为一个引用类型的过程如下。
(1)检查该对象实例是否为某个给定的值类型装箱后的值。
(2)如果是,则将值从实例中复制出来。
(3)赋值给值类型变量。
实例003 演示拆箱操作的实现过程
源码路径 光盘\daima\3\3\ 视频路径 光盘\视频\实例\第3章\003
实例文件chaixiang.cs的主要实现代码如下。
namespace Chaixiang
{
class Program
{
public static void Main()
{
int mm = 50; // 定义值类型变量
// 将值类型变量装箱到引用类型对象
object nn = mm;
Console.WriteLine("装箱:值为{0},装箱对象为{1}", mm, nn);
int zz = (int)nn; // 取消装箱
Console.WriteLine("拆箱:装箱对象为{0},值为{1}", nn, zz);
Console.ReadKey();
}
}
}
范例005:使用LINQ与正则表达式筛选聊天记录
源码路径:光盘\演练范例\005视频路径:光盘\演练范例\005范例006:检索XML文档中的数据
源码路径:光盘\演练范例\006视频路径:光盘\演练范例\006\
在上述代码中,首先定义了变量mm的数值类型为int,且初始值为50;然后对mm的值进行装箱处理为对象nn,具体过程如下。
- 将变量mm的值50进行装箱,转换为对象nn。
- 将变量nn的值进行拆箱处理,转换为变量zz。
经过“csc /out:zhuangxiang.exe zhuangxiang.cs”命令编译处理后,程序执行结果,如图3-7所示。
图3-7 实例执行结果
在上述拆箱处理过程中,必须保证变量的类型前后一致,否则将会出现异常。例如,将上述实例中的拆箱处理代码进行如下修改:
double zz = (double)nn;
修改后的执行结果如图3-8所示。
图3-8 实例执行结果
从图3-8所示的执行结果可以看出,程序只执行了装箱操作,而没有执行拆箱操作。如果使用Visual Studio 2012运行,则会在其中输出异常提示信息,如图3-9所示。
图3-9 Visual Studio 2012的异常提示
共有条评论 网友评论