基础中的基础——数据类型转换

1. 为什么要进行数据转换 ?

首先,为什么要进行数据转换,拿值类型例子说明一下,

比如:我们要把 23 角零钱,换成 2.30 元,就需要把整形转换成小数型。

再比如我们转换一个引用类型的数据,前面说过我们自定义类属于引用类型,假如我们定义了两个类,一个类叫“白猫”,一个类叫“黑猫”,我们要让他们都归为“猫”这个类(不管黑猫白猫,能捉老鼠就是好猫),这种情况就需要将白猫和黑猫这两个类转换成“猫”类。

因此为了运算方便,我们经常要进行不同数据类型间的转换。而且计算机在存储数据的时候,因为数据长度等不同,占用的存储空间要根据预定义好的类型事先分配。在存取之前要进行数据类型的转换。

2.C#类型转换的方式:隐式转换、显式转换、用户自定义转换、使用帮助程序类的转换

隐式转换:由于该转换是一种安全类型的转换,不会导致数据丢失,因此不需要任何特殊的语法。 例如,从较小整数类型到较大整数类型的转换以及从派生类到基类的转换都是这样的转换。

显式转换(强制转换):显式转换需要强制转换运算符。 在转换中可能丢失信息时或在出于其他原因转换可能不成功时,必须进行强制转换。典型的例子包括从数值到精度较低或范围较小的类型的转换和从基类实例到派生类的转换。

用户定义的转换:可以定义一些特殊的方法来执行用户定义的转换,从而使不具有基类–派生类关系的自定义类型之间可以显式和隐式转换。

使用帮助程序类的转换:若要在不兼容的类型之间进行转换,例如在整数与 DateTime 对象之间转换,或者在十六进制字符串与字节数组之间转换,则可以使用 BitConverter 类、 Convert 类和内置数值类型的 Parse 方法,例如 Int32.Parse

3. 类型转换方式选择

C#已经为我们提供了一个很好的类型转换方式,那么在进行类型转换的时候,可以按照如下的方式进行选择。

类型转换 使用选择
Object => 已知引用类型 使用as操作符来完成
Object => 已知值类型 先使用is操作符来进行判断,再用类型强转方式进行转换
已知引用类型之间转换 首先需要相应类型提供转换函数,再用类型强转方式进行转换
已知值类型之间转换 最好使用系统提供的Convert类所涉及的静态方法

4.类型转换操作符is 和 as

通过上表,我们知道:

A.这两种操作符,都用于从未知类型转换到已经类型

B.is 在转换前,需要进行类型判断,再使用强制转换,as则不需要校验,直接转换

C.as校验,转换失败后,不引发异常,返回null,属于安全类型转换; is 在使用前要先确定 是不是兼容类型,如果转换失败,抛出异常。

D. 他们都属于引用类型显式转换

5.装箱和拆箱转换( B oxing,UnBoxing)

主要是值类型与引用类型之间相互转换

如: object obj 1= 10;

int i = (int)obj; // 拆箱

int j = 100;

object obj2 = j; // 装箱

6. 已知值类型转换类

表 3 中介绍了几种转换方式的选择,对于已知值类型,我们推荐使用系统类提供静态方式进行转换。

下面有必要对常用类进行说明

枚举转换

枚举类型与其他任何类型之间不存在隐式转换。而和枚举类型相关的显式转换包括:

a. 从所有整数类型(包括字符类型)和实数类型到枚举类型的显式转换;

b. 从枚举类型到所有整数类型(包括字符类型)和实数类型的显式转换;

c. 从枚举类型到枚举类型的显式转换。

内置数值类型的 Parse 和 T ryParse

示例:

bool result = Int32.TryParse(value, out number);

它们两个区别在于TryParse不会引发异常

Convert 类

将一个基本数据类型转换为另一个基本数据类型。

Convert方法比较多,下面列举几个常用的

示例:int iNumber = System.Convert.ToInt32(dNumber);

更多方法,详细请查询MSDN BitConverter

BitConverter 类

将基础数据类型与字节数组相互转换。

方法较多,详细请查询MSDN BitConverter 类

将字节数组转换为 int

返回类型 方法
bool ToBoolean(Byte, Int32)
char ToChar(Byte, Int32)
double ToDouble(Byte, Int32)
short ToInt16(Byte, Int32)
int ToInt32(Byte, Int32)
long ToInt64(Byte, Int32)
float ToSingle(Byte, Int32)
ushort ToUInt16(Byte, Int32)
uint ToUInt32(Byte, Int32)
ulong ToUInt64(Byte, Int32)

示例一:

byte[] bytes = { 0, 0, 0, 25 }; int i = BitConverter.ToInt32(bytes, 0);Console.WriteLine("int: {0}", i);// Output: int: 25

示例二:

byte[] bytes = BitConverter.GetBytes(201805978);Console.WriteLine("byte array: " + BitConverter.ToString(bytes));

// Output: byte array: 9A-50-07-0C

日期类转换

字符串转日期 string dateString = "5/1/2008 8:30:52 AM"; DateTime date1=DateTime.Parse(dateString,System.Globalization.CultureInfo.InvariantCulture);

日期转字符串 DateTime dat1 = new DateTime();string datastr= dat1.ToString(System.Globalization.CultureInfo.InvariantCulture);

要点:

1. C#中(int)、int.Parse()、int.TryParse()和Convert.ToInt32()的区别

1) 对于转换对象, Convert.ToInt32() 可以为多种类型(例出数字类型外 bool , DateTime 等), int.TryParse() 和 int.Parse() 只能是整型字符串类型(即各种整型 ToString() 之后的形式,不能为浮点型,否则 int.Parse() 就会出现输入的字符串格式不正确的错误, int.TryParse() 也会返回 false ,输出参数为 0 ), (int) 只能是数字类型(例 float,int,uint 等);

2 )对于空值 NULL ,从运行报错的角度讲, (int) 强制转换和 int.Parse() 都不能接受 NULL ; Convert.ToInt32() 其实是在转换前先做了一个判断,参数如果为 NULL ,则直接返回 0 ,否则就调用 int.Parse() 进行转换, int.TryParse() 其实是对 int.Parse() 做了一个异常处理,如果出现异常则返回 false ,并且将输出参数返回 0 ;

3 )针对于浮点型的取舍问题,浮点型只有 Convert.ToInt32() 和 (int) 能进行转换,但是也是进行取舍了的, Convert.ToInt32() 采取的取舍是进行四舍五入,而 (int) 则是截取浮点型的整数部分,忽略小数部分,例如 Convert.ToInt32(1.499d) 和 (int)1.499d 都返回 1 , Convert.ToInt32(1.5d) 返回 2 ,而 (int)1.5d 还是返回 1 ;

4 )关于溢出,将大的数据类型转换为小的数据类型时 Convert.ToInt32() 和 int.Parse() 都会报溢出错误,值对于 Int32 太大或太小,而 (int) 不报错,但是返回值为 -1 。

如此可见,我们在进行数据转换前选择转换方法要谨慎,如果是数字类型可以考虑直接用 (int) 强制转换,如果是整型字符串类型的,考虑用 int.Parse() 进行转换,如果不是这两种类型,再考虑用 Convert.ToInt32() 进行转换。

2.类型转换操作符is 和 as 区别

1)这两种操作符,都用于从未知类型转换到已经类型

2 ) is 在转换前,需要进行类型判断,再使用强制转换,as则不需要校验,直接转换

3)as校验,转换失败后,不引发异常,返回null,属于安全类型转换; is 在使用前要先确定 是不是兼容类型,如果转换失败,抛出异常。

4)他们都属于引用类型显式转换