目录
C#转换
1.什么是转换
转换是接受一个类型的值并使用它作为另一个类型的等价的值的过程。
2.隐式转换和显式转换
有些数据类型的转换不会丢失数据或精度,C#会自动做这些转换,这叫做隐式转换。例如将8位的值转换为16位的值。
零扩展:从位数更小的无符号类型转换为位数更大的无符号类型时,目标类型多出来的最高位以0填充。
符号扩展:从位数更小的有符号类型转换为位数更大的有符号类型时,目标类型多出来的最高位以1填充。
有些数据类型的转换会丢失数据或者溢出,C#不会自动做这些转换,如果仍然需要进行转换,就必须使用显式转换(强制转换)。使用显示转换的表达式叫做强制转换表达式。
4.转换的分类
5.数字转换
任何数字类型都可以(隐式或显式)转换为其他数字类型。
5.1数字的隐式转换和显式转换
图一:数字转换
图二:数字隐式转换(箭头方向上有路径的为隐式转换,无路径的为显式转换)
5.2溢出检测上下文
C#提供了整数类型转换时,检测结果是否溢出的方式。如果在转换时产生溢出,将抛出OverflowException
异常。
- 代码片段是否被检查称作溢出检测上下文。
- 默认的溢出检测上下文是不检查。
checked运算符和unchecked运算符:
//checked运算符
ushort sh = 2000;
byte sb = checked((byte)sh);
//unchecked运算符
ushort sh = 2000;
byte sb = checked((byte)sh);
checked语句和unchecked语句:
//checked语句
checked
{
ushort sh = 2000;
byte sb = (byte)sh;
}
//unchecked语句
unchecked
{
ushort sh = 2000;
byte sb = (byte)sh;
}
6.引用转换
我们已经知道引用类型的对象由内存中的两部分组成:引用和数据。
- 引用保存的信息中包含了引用指向的数据类型。
- 引用转换发生时,目标类型的变量存储了与源类型变量指向堆中相同位置的引用,但是把数据类型“标记”为目标类型。
6.1隐式引用转换
1.所有引用类型都可以被隐式的转换为object
类型。
2.任何类型可以隐式转换到它继承的接口。
3.类可以隐式转换到它继承链中的任何类和它实现的任何接口。
6.2显式引用转换
1.从object
类型到任何引用类型的转换。
2.从基类到从它继承的类的转换。
7.装箱和拆箱
7.1装箱
将值类型的数据转换为引用类型时,发生装箱转换。
已知:
C#中所有类型都派生自
object
类型。
值类型的数据存储在栈中。
引用类型的数据的引用部分存储在栈中,数据部分存储在堆中。
原理是:
在堆上创建值类型的对象。
将值类型的数据复制到值类型的对象。
返回值类型的对象的引用。
特点是:
装箱转换是隐式转换。
装箱转换是创建副本,因此原始值类型和引用类型副本均可独立操作。
7.2拆箱
拆箱转换是把装箱后的对象转换回值类型的过程。
原理是:
检测到要拆箱的对象实际是值类型的装箱值。
把对象的值复制到值类型变量。
特点是:
拆箱是显示转换。
8.用户自定义转换
除了标准转换,还可以为类和结构定义隐式和显式转换。
格式:
需要注意的是:
除了
Implicit
和explicit
关键字外,隐式和显式转换的声明语法是一样的。
需要public
和static
修饰符。
只可以为类和结构定义用户自定义转换。
不能重定义标准隐式转换或显式转换。
源类型和目标类型必须是不同的类型。
源类型和目标类型不能通过继承关联,也就是说,源类型不能继承自目标类型,目标类型也不能继承自源类型。
源类型和目标类型都不能是接口类型或object
类型。
转换运算符必须是源类型或目标类型的成员。
对于相同的源类型和目标类型,不能声明隐式转换和显式转换。
8.is运算符和as运算符
8.1 is运算符
使用is
运算符检查转换是否可以通过以下方式转换完成,若可以转换返回true
,否则返回false
。
引用转换
装箱转换
拆箱转换
class TypeA { }
class TypeB { }
static void Main(string[] args)
{
TypeA typeA = new TypeA();
TypeB typeB = null;
if (typeA is TypeB)
{
//..
}
Console.ReadLine();
}
需要注意的是:is
运算符只可以用于引用转换以及装箱、拆箱转换,不能用于用户自定义转换。
8.2 as运算符
as
运算符和强制转换运算符类似,只是它不抛出异常。如果转换失败,它返回null
而不是抛出异常。
class TypeA { }
class TypeB { }
static void Main(string[] args)
{
TypeA typeA = new TypeA();
TypeB typeB = typeA as TypeB ;
if (typeB != null)
{
//..
}
Console.ReadLine();
}
需要注意的是:as
运算符只可以用于引用转换以及装箱,不能用于用户自定义转换和拆箱转换。