类型转换的一个重要考虑因素是转换的结果是否在目标数据类型的范围内。
宽化转换是指将一个值转换为能够容纳原始数据所有可能值的数据类型。 扩大转换会保留源值,但可以更改其表示形式。 如果从整型类型转换为Decimal
,或从Char
转换为String
,则会发生此情况。
缩小转换会将一个值更改为一种可能无法存储所有可能值的数据类型。 例如,将小数值转换为整型类型时,将对其进行舍入,并且将转换为 Boolean
的数值类型简化为 True
或 False
。
扩大转换
下表显示了标准扩大转换。
数据类型 | 扩展为数据类型 1 |
---|---|
SByte |
SByte 、Short 、Integer 、Long 、Decimal 、Single 、Double |
字节 |
Byte 、Short 、UShort 、Integer 、UInteger 、Long 、ULong 、Decimal 、Single 、Double |
短 |
Short 、Integer 、Long 、Decimal 、Single 、Double |
UShort |
UShort 、Integer 、UInteger 、Long 、ULong 、Decimal 、Single 、Double |
整数 |
Integer 、、Long Decimal 、Single Double 2 |
UInteger |
UInteger 、、Long ULong 、Decimal 、Single Double 2 |
长 |
Long 、、Decimal Single 、Double 2 |
ULong |
ULong 、、Decimal Single 、Double 2 |
十进制 |
Decimal
Single 、Double 2 |
单 |
Single 、Double |
双 | Double |
任何枚举类型 (Enum) | 它的基础整型类型,以及基础类型扩大到的任何类型。 |
字符 |
Char 、String |
Char 数组 |
Char 数组 String |
任意类型 | 对象 |
任何派生类型 | 从中派生出它的任何基类型3。 |
任意类型 | 它实现的任何接口。 |
无 | 任何数据类型或对象类型。 |
1 根据定义,每个数据类型都会扩大到其自身。
2 从Integer
、、UInteger
Long
、ULong
或Decimal
转换到Single
或Double
可能导致精度损失,但永远不会丢失数量级。 从这个意义上说,它们不会产生信息丢失。
3 从派生类型到其某个基类型的转换都是扩大转换,这可能令人惊讶。 理由是派生类型包含基类型的所有成员,因此它限定为基类型的实例。 相反,基类型不包含派生类型定义的任何新成员。
扩大转换在运行时总是会成功,绝不会导致数据丢失。 无论 Option Strict 语句是否将类型检查开关设置为 On
或 Off
,都始终可隐式执行它们。
收缩转换
标准收缩转换包括:
上表中的扩大转换的反向方向(每个类型扩大到其自身的情况除外)
布尔值和任意数值类型之间的任一方向转换
从任何数值类型转换为任何枚举类型 (
Enum
)从数据类型或对象类型转换为派生自它的类型
缩小转换并不总是在运行时成功,并且可能会失败或产生数据丢失。 如果目标数据类型无法接收正在转换的值,则会发生错误。 例如,数字转换可能会导致溢出。 编译器不允许隐式执行收缩转换,除非 Option Strict 语句将类型检查开关设置为 Off
。
注释
从集合中的 For Each…Next
元素到循环控制变量的转换中,窄化转换错误被忽略。 有关详细信息和示例,请参阅 For Each...Next 语句 中的“缩小转换”部分。
何时使用收缩转换
如果知道源值可以转换为目标数据类型,而不会出错或数据丢失,则可以使用缩小转换。 例如,如果你有一个 String
,你知道它含有“True”或“False”,则可以使用 CBool
关键字将其转换为 Boolean
。
转换过程中的异常
扩大转换始终会成功,因此它们不会引发异常。 窄化转换在失败时最常会引发以下异常:
InvalidCastException - 如果未在两种类型之间定义转换
OverflowException—(仅整型类型)如果转换后的值对于目标类型而言太大
如果某个类或结构定义一个 CType 函数,该函数充当与该类或结构之间的转换运算符,那么 CType
可能会引发它认为合适的任何异常。 此外,CType
可能会调用 Visual Basic 函数或 .NET Framework 方法,而这些方法可能会引发各种异常。
引用类型转换期间的更改
从引用类型进行转换只复制指向值的指针。 该值本身既不会复制也不以任何方式更改。 唯一可以更改的就是保存指针的变量的数据类型。 在下面的示例中,数据类型从派生类转换为其基类,但两个变量现在指向的对象保持不变。
' Assume class cSquare inherits from class cShape.
Dim shape As cShape
Dim square As cSquare = New cSquare
' The following statement performs a widening
' conversion from a derived class to its base class.
shape = square