热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

七、转换操作

七、转换操作7.1导言转换操作改变一种类型的变量的值,以便它可以用于

七、转换操作

7.1 导言

转换操作改变一种类型的变量的值,以便它可以用于另一种类型的变量。转换可以是加宽缩小。扩大转换总是保留源变量的值,因为目标变量可以完全容纳源变量的可能值的范围。因此,这种类型的转换在程序执行期间总是成功,因为它不会导致数据丢失。另一方面,收缩转换可能不会保留源变量的值,因为目标变量不能完全容纳源变量的整个可能值范围。因此,在程序执行期间,这种类型的转换可能不会成功,因为可能会发生溢出异常。

在本章中,我们将从扩大转换开始。正如我们将看到的,在 C# 程序中,扩展转换是自动执行的,因为数据不能在转换中丢失。这种转换是隐式地执行的(即,转换发生不需要特殊的语法)。接下来,我们将讨论收缩转换,它是在 C# 程序中自动执行的而不是,因为数据可能会在转换中丢失。这些转换是显式地执行的(即,转换发生需要特殊的语法)。最后,我们将讨论 Convert 类。这个静态类转换一种类型的变量中的值,以便可以在另一种类型的变量中使用它。****

*## 7.2 扩大转换

只要目标类型可以完全容纳源类型的可能值范围,就可以执行扩大转换(也称为隐式转换或强制转换)。因此,扩大转换总是可以隐式执行。例如,当我们想要将 Int16(即 16 位有符号整数)转换为 Int32(即 32 位有符号整数)时,或者当我们想要将 Int32(即 32 位有符号整数)转换为 Double(即 64 位双精度浮点数)时,可以执行扩大转换。

扩大转换不需要特殊的语法,并且是自动执行的,因为在转换过程中不会丢失任何数据,也就是说,不会对任何数据进行舍入(从精度较低的类型转换为精度较高的类型)或截断(从较小的幅度类型转换为较大的幅度类型)。这种转换被称为类型安全

表 7-1 显示了扩大数值转换的列表。请注意,表中没有到 Char 类型的扩大转换。Single 和 Double 类型与 Decimal 类型之间也没有任何扩大转换。请记住,当从 Int32、UInt32、Int64 或 UInt64 转换为 Single 以及从 Int64 或 UInt64 转换为 Double 时,精度(而不是幅度)可能会丢失。

表 7-1

扩大数字转换列表

|

。网络类型

|

描述

|

可以隐式转换为…

|
| --- | --- | --- |
| 布尔代数学体系的 | 一个布尔值(真或假)。 | 钠 |
| 字节 | 一个 8 位无符号整数。 | Int16,UInt16,Int32,UInt32,Int64,UInt64,单精度,双精度,十进制 |
| 茶 | Unicode (16 位)字符。 | UInt16,Int32,UInt32,Int64,UInt64,单精度,双精度,十进制 |
| 小数 | 十进制(128 位)值。 | 钠 |
| 两倍 | 双精度(64 位)浮点数。 | 钠 |
| Int16 | 16 位有符号整数。 | Int32,Int64,单精度,双精度,十进制 |
| Int32 | 32 位有符号整数。 | Int64,单精度,双精度,十进制 |
| Int64 | 64 位有符号整数。 | 单精度、双精度、小数 |
| Sbyte(字节) | 一个 8 位有符号整数。 | Int16,Int32,Int64,单精度,双精度,十进制 |
| 单一的 | 单精度(32 位)浮点数。 | 两倍 |
| UInt16 | 16 位无符号整数。 | Int32,UInt32,Int64,UInt64,单精度,双精度,十进制 |
| UInt32 | 32 位无符号整数。 | Int64,UInt64,单精度,双精度,十进制 |
| UInt64 | 64 位无符号整数。 | 单精度、双精度、小数 |
| 参考 |
| T2https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/implicit-numeric-conversions-table |

当对包含不同类型精度和/或大小的数字变量的数学表达式求值时,也会发生扩大转换。在这种情况下,在对表达式求值之前,具有较低精度类型或较小幅度类型的操作数会自动转换为表达式中使用的最精确类型或最大幅度类型。图 7-1 显示了一些扩大转换的例子。

请注意,在 01 和 02 处,较小的幅度类型被隐式转换为较大的幅度类型。

请注意 03 和 04,不太精确的类型被隐式转换为更精确的类型。从 04 可以看出,不是所有的浮点数都能精确地用二进制表示。这就是为什么单精度值 12345.56789f 由双精度值 12345.568359375 表示,这是 12345.56789f 的近似值。

请注意,在 05 处,i16Number2 和 i16Number3(都是 16 位有符号整数)被隐式转换为与 dblNumber1(一个双精度 64 位浮点数)相同的类型,然后再进行表达式求值。

img/493603_1_En_7_Fig1_HTML.png

图 7-1

扩大转换的示例

7.3 收缩转换

每当目标类型无法完全容纳源类型的可能值范围时,就必须执行收缩转换(也称为显式转换或强制转换)。因此,收缩转换必须始终显式执行。例如,当我们要将 Int32(即 32 位有符号整数)转换为 Int16(即 16 位有符号整数)或者要将 Double(即 64 位双精度浮点数)转换为 Int32(即 32 位有符号整数)时,必须执行收缩转换。

收缩转换需要特殊的语法,并且不会自动执行,因为数据可能会在转换中丢失。更具体地说,数据可以向零舍入到最接近的整数(例如,当从十进制类型转换到整数类型时),或者数据可以被截断(例如,当从双精度或单精度类型转换到整数类型时)。这种转换不是类型安全的。

在 C# 中,收缩转换需要使用转换运算符。转换运算符采用两个括号之间的类型形式。例如,要将 Single 类型的变量转换为 SByte 类型的变量,我们需要在要分配给 SByte 变量的 Single 变量之前包含(SByte ),如下所示

sbyNumber = (SByte)sinNumber;

当我们使用一个 cast 操作符时,我们告诉编译器我们想要强制从一个较宽的类型转换到一个较窄的类型,并且我们知道在这个过程中数据可能会丢失。将一种类型转换为另一种类型时,请记住


  • 当十进制类型被转换为整数类型时,十进制值将被向零舍入到最接近的整数。如果得到的整数值超出整数类型的范围,将发生溢出异常。


  • 当 double 或 single 类型被强制转换为 integer 类型时,double 或 single 值将被截断。如果得到的整数值超出整数类型的范围,将发生溢出异常。


  • 当双精度类型被转换为单精度类型时,双精度值将被舍入到最接近的单精度值。如果 double 值太小而不适合 single 类型,则 single 值将为零。如果双精度值太大而不适合单精度类型,则单精度值将为无穷大。


  • 当单精度或双精度类型被转换为十进制类型时,单精度或双精度值将被舍入到最接近的十进制数(如有必要,在第 28 个小数位之后)。如果单精度或双精度值太小而不能表示为十进制类型,则十进制值将为零。如果单精度值或双精度值不是数字(NaN)、无穷大或太大而无法表示为小数类型,将发生溢出异常。


  • 当十进制类型被转换为单精度或双精度类型时,十进制值将被舍入到最接近的双精度或单精度值


表 7-2 显示了缩小数值转换的列表。请注意,表中的布尔类型不能显式转换为另一种类型。

表 7-2

收缩数字转换列表

|

。网络类型

|

描述

|

可以显式转换为…

|
| --- | --- | --- |
| 布尔代数学体系的 | 一个布尔值(真或假)。 | 钠 |
| 字节 | 一个 8 位无符号整数。 | SByte, Char |
| 茶 | Unicode (16 位)字符。 | SByte、Byte、Int16 |
| 小数 | 十进制(128 位)值。 | SByte、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Char、Single、Double |
| 两倍 | 双精度(64 位)浮点数。 | 位元组、位元组、Int16、UInt16、Int32、Int64、UInt64、Char、Single、Decimal |
| Int16 | 16 位有符号整数。 | 位元组、位元组、uint16、UInt32、uint64、Char |
| Int32 | 32 位有符号整数。 | 位元组、位元组、Int16、UInt16、UInt32、UInt64、Char |
| Int64 | 64 位有符号整数。 | 位元组、位元组、Int16、UInt16、Int32、UInt64、Char |
| Sbyte(字节) | 一个 8 位有符号整数。 | 字节、UInt16、UInt32、UInt64、Char |
| 单一的 | 单精度(32 位)浮点数。 | 字节,字节,Int16,UInt16,Int32,Int32,Int64,UInt64,Char,十进制 |
| UInt16 | 16 位无符号整数。 | 交换,交换,16,查尔 |
| UInt32 | 32 位无符号整数。 | 交换,交换,Int16,UInt16,Int16,Char |
| UInt64 | 64 位无符号整数。 | SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, Char |
| 参考 |
| T2https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/explicit-numeric-conversions-table |

图 7-2 显示了一些收缩转换(即强制转换)的例子。

请注意,在 01 和 02 处,较大的幅度类型被显式转换为较小的幅度类型。

请注意,在 03 和 04 处,较大幅度和较精确的类型被显式转换为较小幅度和较不精确的类型。如 04 所示,数字的小数部分被截断。

请注意,在 05 处,较大幅度的有符号类型被显式转换为较小幅度的无符号类型。可以看到,符号被截断,结果很奇怪。这强调了仔细测试包含强制转换的代码的重要性。

请注意,在 06 处,较大的幅度类型被显式转换为较小的幅度类型,但是较小的幅度类型太小,无法容纳较大的幅度类型。注意,在这个场景中没有发生溢出错误,结果很奇怪。这再次强调了仔细测试包含强制转换的代码的重要性。

img/493603_1_En_7_Fig2_HTML.png

图 7-2

收缩转换的示例

7.4 转换类别

Convert 类是一个静态类,它转换一种类型的变量中的值,以便可以在另一种类型的变量中使用。支持的类型包括 Boolean、Byte、Char、DateTime、Decimal、Double、Int16、Int32、Int64、SByte、Single、String、UInt16、UInt32 和 UInt64。根据源变量中的值和目标值的精度和大小,调用 Convert 类的方法时可能会发生五种情况。这些是


  • 不执行任何转换。当我们试图将一种类型的变量转换为与相同的类型的变量时,就会出现这种情况(例如,将 Double 转换为 Double)。在这种情况下,该方法只返回源变量的值。


  • 执行成功的转换。当执行扩大转换或在不丢失数据的情况下执行收缩转换时,会出现这种情况。在任一情况下,该方法都返回与源变量中的值相同的值。当转换仅导致精度损失时(例如,由于舍入而丢失小数点),转换也被认为是成功的。


  • 引发了 FormatException。当我们试图将一个字符串类型转换为另一个类型,并且字符串值的格式不正确时,就会发生这种情况。当要转换为


    • 布尔类型不等于“真”或“假”


    • 字符类型由多个字符组成


    • 日期时间类型不是有效的日期和时间


    • 数字类型不是有效的数字




  • 引发了 InvalidCastException。当我们试图执行没有意义的转换时,就会发生这种情况。当我们尝试从转换时,会引发 InvalidCastException


    • 将字符转换为布尔值、日期时间、小数、双精度或单精度


    • 布尔值、日期时间、十进制、双精度或单精度到字符


    • DateTime 转换为任何其他类型(字符串除外)


    • DateTime 的任何其他类型(字符串除外)




  • 引发 OverflowException。当我们试图执行导致数据丢失的收缩转换时(例如,将值为 256 的 UInt16 转换为字节,后者最多只能存储 255 的值),就会出现这种情况。


表 7-3 显示了 Convert 类的一些属性、方法和事件。在表中,术语值类型表示. NET 中支持的值类型的 any 。请注意,扩大转换和收缩转换都受支持。

表 7-3

Convert 类的一些属性、方法和事件

| 转换类 1 类 |
| 命名空间系统 |
| 属性 |
| 钠 |   |
| 方法 |
| toboonline(123t0)【货币类型】T1) | 将指定值类型的值转换为等效的布尔值。 |
| 字节( 值类型 ) | 将指定值类型的值转换为等效的 8 位无符号整数。 |
| 栃木〔t0〕value type〔t1〕 | 将指定值类型的值转换为等效的 Unicode 字符。 |
| today time(value type) | 将指定值类型的值转换为等效的日期和时间值。 |
| ToDecimal( Valuetype ) | 将指定值类型的值转换为等效的十进制数。 |
| ToDouble( Valuetype | 将指定值类型的值转换为等效的双精度浮点数。 |
| 屋顶 16( Valuetype | 将指定值类型的值转换为等效的 16 位有符号整数。 |
| 屋顶 32( Valuetype | 将指定值类型的值转换为等效的 32 位有符号整数。 |
| 屋顶 64( Valuetype | 将指定值类型的值转换为等效的 64 位有符号整数。 |
| 托字节( 值类型 ) | 将指定值类型的值转换为等效的 8 位有符号整数。 |
| ToSingle( Valuetype ) | 将指定值类型的值转换为等效的单精度浮点数。 |
| ToString( Valuetype | 将指定值类型的值转换为等效的字符串表示形式。 |
| TouInt16( 值型 ) | 将指定值类型的值转换为等效的 16 位无符号整数。 |
| TouInt32( 值型 ) | 将指定值类型的值转换为等效的 32 位无符号整数。 |
| TouInt64( 值型 ) | 将指定值类型的值转换为等效的 64 位无符号整数。 |
| 事件 |
| 钠 |   |
| 参考 |
| T2https://msdn.microsoft.com/en-us/library/system.convert(v=vs.110).aspx |

在从更精确的数字类型转换为不太精确的数字类型时,在决定是使用收缩转换(即强制转换)还是表面上等效的 Convert 类方法时,一定要谨慎。这是因为数值转换会截断,而数值转换会舍入到最接近的偶数。在 C# 中,默认情况下,以 5 结尾的十进制值在舍入过程中根据被舍入的数字向上或向下舍入到最接近的偶数值。例如,数字 1.5 和 3.5 将分别向上舍入到 2 和 4,而数字 2.5 和 4.5 将分别向下舍入到 2 和 4。因此,不会发生舍入到奇数值的情况。这种方法遵循标准的银行家舍入惯例。使用这种特殊舍入方法的原因是,在对大量数字进行舍入时,它可以避免舍入偏差。图 7-3 显示了一些将一种类型转换成另一种类型的例子。可以看出,正在执行扩大转换和收缩转换。**

请注意 01–03,较小的量级类型正在转换为较大的量级类型。

请注意,在 04 处,较小的幅度类型也被转换为较大的幅度类型。请注意,并非所有浮点数都可以用二进制精确表示。这就是为什么单精度值 7.1234f 由双精度值 7.1234002113342285 表示,这是 7.1234f 的近似值。

请注意 05–09,较大的量级类型正在转换为较小的量级类型。

请注意,在 10 处,较大的幅度类型也被转换为较小的幅度类型。注意结果是按照庄家四舍五入的规则四舍五入的。

img/493603_1_En_7_Fig3a_HTML.png img/493603_1_En_7_Fig3b_HTML.png

图 7-3

将一种类型转换为另一种类型的示例

让最终用户在文本框控件中输入一个值,然后将该输入(以字符串类型存储在控件的文本属性中)转换为另一种类型,这是 ASP.NET Web 应用中非常常见的操作。这是因为我们必须经常在代码后面的非字符串操作(例如,数值计算)中使用该输入。图 7-4 展示了一些将文本框控件的文本属性转换成另一种类型的例子。

请注意,在 01 和 02 处,转换只需要一个步骤。

但是,请注意 03–06,转换需要两个步骤。在这些示例中,请注意,由于最终用户可能输入了错误数据,因此很有可能会引发异常。这强调了第 5 章“数据验证控制”中讨论的数据验证技术以及第 6 章“赋值操作”中讨论的异常处理技术的重要性

img/493603_1_En_7_Fig4_HTML.png

图 7-4

将 TextBox 控件的 Text 属性转换为另一种类型的示例

Footnotes [1](#Fn1_source)
所有属性、方法和事件描述都直接取自微软的官方文档。为了节省空间,省略了用于处理该类事件的事件处理程序方法。有关该类的所有方法,请参见参考。
 

*


推荐阅读
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了如何将CIM_DateTime解析为.Net DateTime,并分享了解析过程中可能遇到的问题和解决方法。通过使用DateTime.ParseExact方法和适当的格式字符串,可以成功解析CIM_DateTime字符串。同时还提供了关于WMI和字符串格式的相关信息。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
author-avatar
张俊凯宜珮
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有