4.2 数据类型之间的转换
类型转换从根本上说是类型铸造,或者说是把数据从一种类型转换为另一种类型。在C#中,转换分为隐式转换和显式转换,本节将详细介绍这两种转换方式,并讲解相关的Convert转换与数值和字符串之间的转换。
4.2.1 隐式转换
隐式类型转换就是指C#默认的以安全方式进行的转换,不会导致数据丢失。隐式转换可能会在许多情况下出现,包括方法调用和赋值语句。如表4-1所示列出了预定义隐式转换的数据类型。
表4-1 隐式类型转换表
例如,将int类型的值隐式转换成long型。
int i=100; //声明一个整型变量i并初始化为100 long j=i; //隐式转换成long型
关于隐式类型转换,需要注意以下几点。
(1)在从int、uint、long或ulong转换为float,以及从long或ulong转换为double时,可能会丢失精度。
(2)不存在针对char类型的隐式转换。
(3)浮点类型与decimal类型之间不存在隐式转换。
(4)int类型的常数表达式可以转换为sbyte、byte、short、ushort、uint或ulong,前提是常数表达式的值处于目标类型的范围内。
4.2.2 显式转换
当类型转换可能会发生数据丢失时,编译器就会要求执行显式转换。显式转换也称为强制转换。强制转换是显式告知编译器用户打算进行转换,并且用户知道可能会发生数据丢失的一种方式。如果要执行强制类型转换,需要在要转换的值或变量前面的括号中指定要强制转换到的类型。
【例4-4】编写程序,将double强制转换为int。
(1)在Visual Studio 2017中,新建名称为“Project4”的文件。
(2)在代码编辑区域输入以下代码。
【程序分析】本例演示了显式类型转换的用法。在代码中,首先定义一个double类型的变量d,并为其赋值为314.159;接着再定义一个int类型的变量i;最后将变量d通过强制类型转换的方式,赋给变量i。但是如不进行强制转换,则该程序不会进行编译。
在Visual Studio 2017中的运行结果如图4-5所示。
由于显式转换包括所有隐式转换和显式转换,因此总是可以使用强制转换表达式,将任何数值类型转换为任何其他的数值类型。如表4-2所示列出了需要进行显式转换的数据类型。
图4-5 显式转换
表4-2 显式类型转换表
显式转换可能会导致精度降低或导致引发异常,所以需要注意以下几点。
(1)将decimal值转换为整型类型时,此值会向零舍入到最接近的整数值。如果生成的整数值处于目标类型的范围之外,则会引发溢出错误。
(2)从double或float值转换为整型类型时,会截断该值。如果生成的整数值处于目标值范围之外,则结果会取决于溢出检查上下文。在已检查的上下文中,引发溢出错误;而在未检查的上下文中,结果是目标类型的未指定值。
(3)将double转换为float时,double值舍入为最接近的float值。如果double值太小或太大,无法匹配目标类型,结果将为零或无穷大。
(4)将float或double转换为decimal时,源值转换为decimal表示形式,并四舍五入到第28位小数后最接近的数。根据源值的值,可能出现以下结果之一:
① 如果源值太小,无法表示为decimal,结果则为零。
② 如果源值为NaN(非数值)、无穷大或太大而无法表示为decimal,则引发溢出错误。
(5)将decimal转换为float或double时,decimal值舍入到最接近的double或float值。
4.2.3 使用Convert进行任意类转换
类型如果是相兼容的两个变量,则可以使用隐式类型转换或者强制类型转换,但是,如果两个变量不兼容,例如说string和int或者string和double类型,这个时候用户就需要一种名叫Convert的转换工厂进行转换。
Convert是专门进行类型转换的类,它能够实现各种基本数据类型之间的装换。C#提供了内置的类型转换方法,如表4-3所示。
表4-3 Convert类的转换方法
【例4-5】编写程序,使用ToInt32方法,将string字符串类型转换成int和double类型并且输出。
(1)在Visual Studio 2017中,新建名称为“Project5”的文件。
(2)在代码编辑区域输入以下代码。
【程序分析】本例演示了Convert类的转换方法。在代码中首先定义字符串类型的变量str,并为其赋值为“123456”;然后通过ToInt32方法,将str的数据分别转换为int类型和double类型。
在Visual Studio 2017中的运行结果如图4-6所示。
图4-6 Convert类的转换方法
注意:使用Convert进行强制类型转换也要满足一个条件只有能够表示成数字的字符串才可以进行转换。
例如:
string num = "123abc"; //不能转换成int数值型
4.2.4 数值和字符串之间的转换
C#中不仅存在数值类型的数据之间的转换,字符串和数值之间也是可以互相转换的,只是方法不同而已。
1. 数值型转换为字符型
数值型数据转换为字符串用ToString()方法即可实现。
例如:
2. 字符串转换为数值型
字符串数据转换为数值型使用Parse ()方法。
(1)使用int.Parse ()方法,将字符串类型转换为整型。
string str="10"; int number=int.Parse (str);
(2)使用double.Parse ()方法,将字符串类型转换为双精度浮点型。
例如:
string str="20"; double number =double.Parse (str);
(3)使用float.Parse ()方法,将字符串类型转换为单精度浮点型。
string str="30"; float number=float.Parse (str);
并不是所有的字符串都可以转换为数值型数据,只有能够表示成数字的字符串才可以进行转换,例如名字“张三”,转换成数字就没有符合的表达式,所以不能实现转换。
注意:Parse ()括号中的参数只能是字符串,不能为其他数据类型。
【例4-6】编写程序,将数值型数据转换为字符串,再通过调用方法,将字符串转换为数据。
① 在Visual Studio 2017中,新建名称为“Project6”的文件。
② 在代码编辑区域输入以下代码。
【程序分析】本例演示了数值和字符串之间的转换。在代码中,首先定义三个变量a、b、c,并对它们初始化赋值;接着调用ToString方法,将这三个变量转换为字符串;最后再调用Parse方法,将转换后的字符串转成数值型数据。
在Visual Studio 2017中的运行结果如图4-7所示。
图4-7 数值和字符串之间的转换
4.2.5 Convert.ToInt32()、(int)与int.Parse()的区别
C#中数据转换的方法很多,本节主要讲解Convert.ToInt32()、(int)与int.Parse()的区别。在实际开发项目的过程中,需要被转换的类型大概分为三大类,分别是空值(null)、数字类型(包含float,double,int,long等)和字符串(string)。
(1)对null值进行类型转换。
例如:
对于空值null,从运行报错的角度讲,(int)强制转换和int.Parse()都不能接受null;Convert.ToInt32()其实是在转换前先做了一个判断,参数如果为null,则直接返回0。
(2)转换数字类型,主要测试double和long类型。
对于double类型:
针对于浮点型的取舍问题,浮点型只有Convert.ToInt32()和(int)能进行转换,但是也是进行取舍了的。Convert.ToInt32()采取的取舍是进行四舍五入,而(int)则是截取浮点型的整数部分,忽略小数部分。
例如,Convert.ToInt32(1.49d)和(int)1.49d都返回1,Convert.ToInt32(1.5d)返回2,而(int)1.5d还是返回1。
对于long类型:
将大的数据类型转换为小的数据类型时,Convert.ToInt32()和int.Parse()都会报溢出错误,值对于Int32太大或太小,而(int)不报错,但是返回值为-1。
(3)转换字符串类型。
Convert.ToInt32()可以转换多种类型(例如非数字类型bool、DateTime等),int.Parse()只能是整型字符串类型(即各种整型ToString()之后的形式,不能为浮点型,否则int.Parse()就会出现输入的字符串格式不正确的错误),(int)只能是数字类型(如float、int、uint等)。