目录
使用关键字 checked 和 unchecked 来设置“ 溢出检测上下文” (291P)
checked 和 unchecked 运算符 (291P)
float 或 double 到 decimal ( 295P )
decimal 到 float 或 double ( 295P )
委托可以隐式转换为 .NET BCL类 和 接口 (297P)
什么是转换
转换( conversion )是接受一个类型的值并使用它作为另一个类型的等价值的过程。
转换后的目标类型的值应和源值一样的, 但其类型为目标类型。
下面举个例子:
第三行代码把var1赋值给var2, 由于它们是两种不同的类型, 在进行赋值之前, var1的值必须先转换为与var2类型相同的值类型。这将通过强制转换表达式来实现, 稍后我们就会看到。
还要注意, var1的类型和值都没有改变。尽管称之为转换, 但只是代表源值作为目标类型来使用, 不是源值转换为目标类型。
转换的类型 (289P)
除了标准转换, 还可以为自定义类型定义隐式转换和显式转换。
还有一个预定义的转换类型, 叫做装箱, 可以将任何值类型转换为:
- object类型;
- System.ValueType类型。
拆箱可以将一个装箱的值转换为原始类型
隐式转换 (287P)
当用一个位数小的类型转换为一个位数大的类型,不会丢失数据和精度。语言会自动做这些转换, 这叫做隐式转换。
从位数更少的源转换为位数更多的目标类型时, 目标类型中多出来的位需要用0或1填充。
- 当从更小的无符号类型转换为更大的无符号类型时, 目标类型多出来的最高位都以0进行填充,这叫做零扩展(zero extension )。
- 当从更小的有符号类型转换为更大的有符号类型时, 目标类型多出来的最高位都以源表达式的符号位进行填充。这样就维持了被转换的值的正确符号和大小。这叫做符号扩展(sign extension )。
- 即使两个变量存储的信息相同,使用不同的类型解释它们时,存储的方式也是不同的。
- 注意: bool 和 string 没有隐式转换; char 存储的是数值,所以 char 被当作数值类型。
这些类型的隐式转换规则是: 任何类型A,只要其取值范围完全包含在类型B的取值范围内,就可以隐式转换为类型B。
例如:假设我们希望把 ushort 类型的值转化为 byte 类型:
- ushort可以保存任何0~65 535之间的值。
- byte只能保存0 ~255之间的值。
- 只要希望转换的 ushort 值小于256,那么就不会损失数据。然而, 如果更大, 最高位的数据会丢失。
下图演示了尝试把值为1365的ushort类型转换为byte类型会导致数据丢失。不是所有源值的最高位都适合目标类型, 会导致溢出或数据丢失。源值是1365, 而目标的最大值只能是 255, 最终字节中的结果值为85 ,而不是1365。
如果说ushort 类型变量中的存储的数值小于256,ushort 就可以转换byte , 但是需要显式转换。
ushort aa = 254;
byte bb = (byte)aa;
WriteLine(bb); // 输出 254
ushort cc = 256;
byte dd = (byte)cc;
WriteLine(dd); //输出0
显式转换 (288P)
对于预定义的类型, C#会自动将一个数据类型转换为另一个数据类型, 但只是针对那些从源 类型到目标类型不会发生数据丢失的情况。也就是说, 对于源类型的任意值在被转换成目标类型时会丢失值的情况, 语言是不会提供这两种类型的自动转换的。如果希望对这样的类型进行转换, 就必须使用显式转换, 使用强制类型表达式。
语法为:
(要转换成的数据类型)表达式
- 注意: 这只是在特殊的情况下可行的,彼此之间几乎没有什么关系的类型或根本没有关系的类型不能进行强制换行。
- 当我们使用强制类型转换时,就意味着可能会丢失数据或精度的后果 。
例如: 下图演示了强制转换表达式将两个ushort类型的值转换为byte类型。对于第一种情况,没有数据丢失。对于第二种情况,最高位丢失了,得到的值是85,很明显不等于源值1365。
使用关键字 checked 和 unchecked 来设置“ 溢出检测上下文” (291P)
我们已经知道了, 显式转换可能会丢失数据并且不能在目标类型中同等地表示源值。对于整数类型, C#给我们提供了关键字 checked 和 unchecked 来选择在程序运行时进行类型转换时检测结果是否溢出。
代码片段是否被检查称作溢出检测上下文。
- 如果我们指定一个表达式或一段代码为checked, CLR(公共语言运行库)会在转换产生溢出时抛出一个 overflowException异常。
- 如果代码不是 没有指定 checked, 则无论是否存在溢出,转换都将继续。
- 默认的溢出检测上下文是不检查。
checked 和 unchecked 运算符 (291P)
checked 和 unchecked 运算符控制表达式的溢出检查上下文,该表达式位于一组括号之间。 表达式不能是方法。 语法如下
语法为:
checked(表达式); unchecked(表达式);
namespace HelloWorld_Console { class Program { static void Main(string[] args) { ushort sh = 2000; byte sb; sb = unchecked((byte)sh); // 大多数重要的位丢失了 Console.WriteLine