C#笔记(转换)

转换是接受一个类型的值并使用它作为另一个类型等价值 的过程。

1 转换的类型

转化类型可分为 预定义用户自定义的
其中预定义又可分为:

  • 数字转换:其又可分为隐式或显式
  • 装箱/拆箱:装箱用于将任何 值类型 转换为: object 类型或 System.ValueType 类型,拆箱用于还原
  • 引用转换:多是基类与派生类的转化

用户自定义的就需要使用到 implicitexplicit 关键字了。

1.1 隐式转换

有些类型的转换不会丢失数据或精度,比如8位的数值转换为16位的数值,语言会自动做这些转换,这叫做 隐式转换

  • 零扩展:从更小的无符号类型转换为更大的无符号类型时,目标类型多出来的最高位都以 0 进行填充,这叫做 零扩展
  • 符号扩展:对于有符号类型的转换而言,额外的高位用 源表达式的符号位 进行填充,这样叫做 符号扩展

1.2 显式转换和强制转换

如果有长类型转换为短类型,目标类型也许无法在不损失数据的情况下提供源值,很多情况下会导致数据溢出丢失。此时还是想要继续转换,就必须使用 显式转换强制转换表达式)。
示例:

(sbyte) varl1; // sbyte 是目标类型,var1 源表达式

1.2.1 溢出检测上下文

显式转化可能会丢失数据并且不能在目标类型中同等地表示源值,对于整数类型,可以通过 checked 运算符和 checked 语句来检测结果是否溢出。
代码片段是否被检测称作为 溢出检测上下文,默认的检测上下文是不检查。

checked 运算符和 unchecked 运算符:

ushort sh = 2000;
byte sb;
sb = unchecked((byte) sh); // 大多数重要的位丢失了
sb = checked((byte) sh); // 抛出overflowException异常

checked 语句和 unchecked 语句,它们与运算符的不同是,它们控制的是语句块:

byte sb;
ushort sh =2000;
checked
{
    sb = (byte) sh;
}

1.2.1 显式数据的丢失状况

数值类型

类型范围大小
sbyte-128 到 127有符号 8 位整数
byte0到255无符号 8 位整数
charU+0000 到 U+ffff16 位 Unicode 字符
short-32,768 到 32,767有符号 16 位整数
ushort0 到 65,535无符号 16 位整数
int-2,147,483,648 到 2,147,483,647有符号 32 位整数
uint0 到 4,294,967,295无符号 32 位整数
long-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807有符号 64 位整数
ulong0 到 18,446,744,073,709,551,615无符号 64 位整数
decimal(-7.9 x 1028 到 7.9 x 1028) / 100 到 28128 位精确的十进制值,28-29 有效位数
float±1.5e−45 到 ±3.4e3832 位单精度
double±5.0e−324 到 ±1.7e30864 位双精度
  • floatdouble 转化为整数类型时,源值会舍掉小数,如果舍掉小数后的值仍不在目标类型的范围内,就根据 溢出检测上下文 来进行下一步操作。

2 引用转换

引用转换接受源引用并返回 一个指向堆中同一位置的引用,只是把引用标记为其他类型,而实际上二者都指向内存中的相同对象

2.1 隐式引用转换

与自动实现的隐式数值转换类似,还有隐式引用转换:

  • 所有引用类型都可以被隐式转换为 object 类型
  • 如何类型都可以隐式转换到他继承的接口
  • 类可以隐式转换到他继承链中的任何类,以及它实现的任何接口

3 装箱和拆箱

包括值类型在类的所有C#类型都派生自 object 类型,只是 值类型 是高效轻量的类型,就是以 object 类型作为桥梁,值类型与引用类型的相互转换

3.1 装箱

默认情况下,值类型在堆上不包括它们的对象组件,如果需要对象组件,可以使用装箱实现。
装箱是 隐式转换,它接受值类型的值,根据这个值在堆上创建一个完整的引用类型对象并返回其引用。其中原始值类型和返回的引用类型,每个都可以独立操作,互不干扰。

int i =12;
object oi = null;
oi = i;

3.2 拆箱

拆箱是把装箱后的对象转换回值类型的过程,拆箱是显式转换。

int i =10;
object oi = i;
int j = (int) oi; // 将一个值拆箱为非原始类型时会抛出InvalidCastException异常

4 用户自定义转换

用户自定义看 这里

在定义类和结构的时候,可以同时为其自定义转换。
定义时要点:

  • 使用 implicitexplicit 关键字,前者是隐式,后者是显式,二者后跟 operator 运算符、目标类型
  • 声明时需要 publicstatic 修饰符
  • 二者不能通过继承关联,二者必须是不同类型
  • 二者都不能是 object 类型或接口类型

例如:

public static implicit operator int(Person p)
{
    return p.Age;
}

5 is 运算符

有些转换是不成功的,就如同用于检测整数转换是否成功的 checked 运算符一样,is 运算符用于测定以下方式是否转换成功,成功返回true

  • 引用转换
  • 装箱/拆箱转换

语法:

Expr is TargetType; // 可以使用 if 语句判断是否为 true,再进行转换

6 as 运算符

as 运算符与强制转换运算符类似,只是它不抛出异常,如果失败,它返回的是 null,所以赋值变量之前要先检查是否为 null
注意:as 运算符只能用于引用转换装箱转换没有拆箱转换)。
语法:

Expr as TargetType;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值