文章著作权归作者所有。转载请联系作者,并在文中注明出处,给出原文链接。

本文原更新于作者的github博客,这里给出链接

什么是转换

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

转换的分类

一般转换

从转换的方式来看,可以分为显式转换隐式转换。显示和隐式最主要的区分点在于,这种转换是否让这个“值”的描述更加“精确”,如果是,那么则是显示转换,否则为隐式转换。例如:玫瑰是植物。如果我们需要更精确地指出玫瑰是一种花,那么我们就需要显式地强调“玫瑰是花的一种”。反过来,玫瑰是花,而花是植物是已知的,这时候我们便不需要特别说明玫瑰是植物了,因为此时它已经包含了这一信息。

一般来说,在不丢失数据的情况下,语言会自动进行预定义对象类型的转换,这种转换称为预定义的隐式转换。对于数字类型雷说,例子即为把int类型的数字10转换为double类型;相对地,在可能发生数据丢失的场合,语言并不会为我们自动进行转换,这时,我们需要做显式转换。

// 显式转换例子
ushort a = 100;
ushort b = 600;
byte c = (byte)a;
byte d = (byte)b;

ushort类型的表示范围是02^16^-1,而`byte`类型的表示范围只有028-1。此时则需要进行显式转换。在上面的例子中,a可以被安全地转换为byte类型的c,但是对于d来说,由于b的值超过了byte的表示范围,在转换过程中则会进行高位截断,也就是说,ushort超出byte的八个高位数值会被忽略,转换后,d的值为600 % 128 = 88。

对于引用类型,由于所有的类都继承了Object,所以都可以被隐式转换为Object类型,类似地,类引用也可以转换为继承链中的任意类引用以及它实现的所有接口引用。引用的显式转换则发生在从基类到派生类的过程中,前提是这个转换不会编译错误,或者说抛出异常。

装箱、拆箱

基于面向对象,还有一种特殊的转换,装箱拆箱转换。

在C#中,所有的类型都派生自Object类型,包括值类型。值类型是高效轻量的类型,他们在堆上存在时并不会包括它所属的对象组件。当我们需要使用这个对象时,我们就会根据这个值组装为一个完整的对象,也就是装箱。装箱也是一种隐式转换,它接受值类型,并根据这个值在堆上创建一个完整对象并返回引用。装箱操作返回的并不是原值的引用,而是一个根据原值组装的对象的副本。

int number = 0;
object obj = number; // 这里隐式地进行了装箱操作
number = 1;
obj = 2; // 此时number的值仍是1;obj中的值只是一个副本,在它身上做的修改不会反馈到原对象上

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

int number = 0;
object obj = number; // 先把number装箱
int number2 = (int)obj; // 显式进行拆箱
// 此时,number、obj、number2对应的值均为0

拆箱的操作结果只能是原始类型,否则会抛出异常。

自定义转换

从转换的定义者来看,还可以分为预定义转换和自定义转换。这个比较容易理解,语言本身帮我们进行的称为预定义转换,其余则是自定义转换。

// 一个例子
public class A {
public int num;
public A(int _num) {
num = _num;
}
// 在C#中,转换是静态方法
// implicit/explicit分别代表隐/显式
public static implicit operator int(A a) {
return a.num;
}
public static implicit operator A(int _num) {
return new A(_num);
}
}

自定义的类型转换有以下规则:

  1. 不能重定义标准的转换
  2. 转换必须以类或结构为单位
  3. 转换源和目标类型必须不同
  4. 对于同源同目标的转换,不可以同时声明其显隐式
  5. 转换操作符必须是源或目标的成员
  6. 源类型和目标类型不能互为继承关系(标准一的细化)
  7. 源类型和目标类型均不能为接口或者Object类型(标准一的细化)

转换的保障

is运算符

通过前面的学习,我们知道了有些转换请求时不成功的,并在运行时抛出异常,这是我们不希望看到的。is运算符可以帮我们确认转换的成功与否。

if (ExpressionA is ExpressionB) {
// Do type conversion
}

is运算符返回值为bool,当ExpressionA的返回值可以被成功转换为ExpressionB的返回值时返回true,但是is的检查只适用于引用转换、装箱、拆箱,并不支持自定义转换。

as运算符

as运算符则是强化版强制转换,并且不会抛出异常,而是在转换失败时返回null

destinationTypeInstance = sourceTypeInstance as DestinationType;
if (destinationTypeInstance != null) {
// Do something
}

注意到,as运算符返回的是引用类型,也就是说,我们可以将其作为赋值运算的右值,而DestinationType则必须为引用类型。

Type Conversion的更多相关文章

  1. JavaScript Type Conversion

    Data Types 5 Data Types string, number, boolean, object, function 3 Object Types object, array, date ...

  2. error: expected constructor, destructor, or type conversion before '.' token

    今天写代码是遇到这样一个问题error: expected constructor, destructor, or type conversion before '.' token:立马网上查,原来是 ...

  3. 【错误】expected constructor, destructor, or type conversion before '.' token - 第八个游侠的日志 - 网易博客

    [错误]expected constructor, destructor, or type conversion before '.' token - 第八个游侠的日志 - 网易博客 [错误]expe ...

  4. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(一)

    题外话:本篇是对之前那篇的重排版.并拆分成两篇,免得没了看的兴趣. 前言 在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起.大概是默认了读者都是有相关经验的 ...

  5. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  6. delphi 10.1 berlin datasnap提交clientdataset.delta报:invalid variant type conversion(类型转换错误)问题的解决

    delphi 10.1 berlin datasnap提交clientdataset.delta报:invalid variant type conversion(类型转换错误)问题的解决,需要打这个 ...

  7. java 反射 报错:Attempt to get java.lang.Integer field "..." with illegal data type conversion to int

    类: Integer id; 反射时: Field f = User.class.getDeclaredField("id"); f.setAccessible(true); in ...

  8. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion

    本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...

  9. [C++] Type Conversion(类型转换)

    Type Conversion(类型转换) Two kinds of type conversion explict type conversion(显式类型转换) impict type conve ...

随机推荐

  1. ubuntu下安装和配置pycharm和pyqt5

    参考网址:https://blog.csdn.net/qq_37541097/article/details/80021315 PyQt是Python语言的GUI编程解决方案之一.可以用来代替Pyth ...

  2. h5跳转

    <!doctype html> <html lang="en" style="width:100%; height:100%"> < ...

  3. AD模块电压采集电路

    之前一直没搞明白模拟电压转换电路,不知道应该怎么计算转换电压,最近一个项目中用到几处模拟电压的采集,硬件是由其他同事设计的,转换公式也是他给的,记录一下: 24V电压采集: 公式:Vout = Vin ...

  4. Exp5 MSF基础应用 20164320 王浩

    1. 实践目标 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实践,如ms08_067; (1分) 1.2 一个针对浏览器的攻击, ...

  5. VUE-004-禁止修改页面显示项,设置el-input,textarea只读方法

    在实际业务需求中,有些内容当初次创建后,即不可再次进行修改变更,因而需要显示的文本内容不允许变更.此时,可通过页面限制防止用户修改. 方法:添加 readonly="true" 或 ...

  6. ADB——模拟手机按键输入

    基本命令 adb 模拟按键输入的命令主要通过 input 进行 Usage: input [<source>] <command> [<arg>...] The s ...

  7. DAX/PowerBI系列 - 查询参数用法详解(Query Parameter)

    PowerBI  - 查询参数用法详解(Query Parameter) 很多人都不知道查询参数用来干啥,下面总结一下日常项目中常用的几个查询参数的地方.(本人不太欢hardcode的东西) 使用查询 ...

  8. 浅析对spring中IOC的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  9. Schlumberger Petrel 2016.3 地震解释 油藏模拟

    Schlumberger Petrel 2016.3 地震解释 油藏模拟世界上顶尖的三维地质建模软件,软件为用户提供的工具可以用于地震解释.地质建模.油藏数 值模拟等方面的使用,清晰的地质模型可以描述 ...

  10. weixin://connectToFreeWifi/协议如何跳转到微信客户端打开在wifi指定任意网页?

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...