C#编程(四十一)----------用户定义的数据类型转换
用户定义的数据类型转换
C#允许定义自己的 数据类型,这意味着需要某些 工具支持在自己的数据类型间进行数据转换.方法是把数据类型转换定义为相关类的一个成员运算符,数据类型转换必须声明为隐式或者显式,以说明怎么使用它.
C#允许用户进行两种定义的数据类型转换,显式和隐式,显式要求在代码中显式的标记转换,其方法是在原括号中写入目标数据类型.
对于预定义的数据类型,当数据类型转换时可能失败或者数据丢失,需要显示转换:
1.把int数值转换成short时,因为short可能不够大,不能包含转换的数值.
2.把所有符号的数据转换为无符号的数据,如果有符号的变量包含一个负值,会得到不正确的结果.
3.把浮点数转换为整数数据类型时,数字的小数部分会丢失.
此时应在代码中进行显示数据类型转换,告诉编译器你知道这会有丢失数据的危险,因此编写代码时把这些可能考虑在内.
注意:如果源数据值使数据转换失败,或者可能会抛出异常,就应把数据类型转换定义为显式.
定义数据类型转换的语法有点类似于运算符重载.
例如:隐式类型转换的代码:
public static inplicit operator float(Current current)
{}
和运算符重载相同,数据类型转换必须声明为public和static.
注意:
当数据类型转换声明为隐式时,编译器可以显式或隐式的调用数据类型转换.
当数据类型转换声明为显式的,编译器只能显式的调用类型转换.
案例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 类型转换
{
class Program
{
static void Main(string[] args)
{
try
{
Current balance = new Current(50, 35);
Console.WriteLine(balance);
Console.WriteLine("balance using tostring() : + " + balance.ToString());
//隐式类型转换
float balance2 = balance;
Console.WriteLine("After converting to float : " + balance2);
//显示类型转换
balance = (Current)balance2;
Console.WriteLine("After converting to Current : " + balance);
float t = 45.63f;
Current c = (Current)t;
Console.WriteLine(c.ToString());
checked
{
balance = (Current)(-50.5);
Console.WriteLine("result is : " + balance.ToString());
}
}
catch (Exception)
{
Console.WriteLine("错误");
}
Console.ReadKey();
}
}
struct Current
{
public uint Dollars;
public ushort Cents;
//构造函数
public Current(uint dollars, ushort cents)
{
this.Dollars = dollars;
this.Cents = cents;
}
//重写ToString()方法
public override string ToString()
{
return string.Format("{0}.{1,-2:00}", this.Dollars, this.Cents);
}
//隐式类型转换
public static implicit operator float(Current value)
{
return value.Dollars + (value.Cents / 100.0f);
}
//显示类型转换
public static explicit operator Current(float f)
{
uint dollars = (uint)f;
ushort cents = (ushort)((f - dollars) * 100);
return new Current(dollars, cents);
}
}
}
将设计两个问题:
1.从float转换为Current得到错误的结果50.34,而不是50.35,----圆整造成的,发生截断问题.
答:如果float值转换为uint值,计算机就会截断多余的数字,而不是去圆整它.计算机数据是通过 二进制存储的,而不是十进制,小数部分0.35不能以二进制形式存储.因为舍弃一部分,故实际转换成的数据要小于0.35,即可以用二进制形式存储的值,然后数字乘以100,得到小于35的数字34,有时候这种阶段是很危险的,避免这种错误的方式时确保在数字转换过程中执行智能圆整操作.
Microsoft编写了一个类System.Convert来完成该任务.System.Convert包含大量的静态方法来执行各种数字转换,我们要使用的是Convert.ToUint16().注意,在使用System.Convert方法会产生额外的性能损耗,所以只有在需要的时候才使用.
注意:System.Convert方法还执行他们自己的溢出检查,所以
Convert.ToUint16((f-dollars)*100);
这样的代码可以不放在checked里面.
2.在试图转换超出范围的值时,没有发生异常.主要是因为:发生溢出的位置根本不在Main例程中--这是在转换运算符的代码中发生的,该代码在Main()方法中调用,该方法没有标记为checked,其解决方法:
代码:
public static explicit operator Current(float f)
{
checked
{
uint dollars = (uint)f;
ushort cents = Convert.ToUInt16((f - dollars) * 100);
return new Current(dollars, cents);
}
}
explicit和implicit属于转换运算符,乳痈这两者可以让我们自定义的类型支持相互交换
explicit表示显示转换,从A->B必须进行强制类型转换:B=(B)A
implicit表示隐式转换,如从B->A只需要直接复制A=B
隐式转换可以让我们的代码看上去更漂亮,更简洁移动,所以最好多使用implicit运算符.不过,如果对象本身在转换时会损失一些信息(如精度),那么我们只能使用explicit运算符,以便在编译期就能警告客户调用.
C#编程(四十一)----------用户定义的数据类型转换的更多相关文章
- C#高级编程四十一天----用户定义的数据类型转换
用户定义的数据类型转换 C#同意定义自己的 数据类型,这意味着须要某些 工具支持在自己的数据类型间进行数据转换.方法是把数据类型转换定义为相关类的一个成员运算符,数据类型转换必须声明为隐式或者显式,以 ...
- [Day2]变量、数据类型转换以及运算符
1.变量 变量是内存中装载数据的小盒子,你只能用它来存取数据 2.计算机存储单元 (1)计算机存储设备的最小信息单元叫“位(bit)”,“比特位” (2)8个比特位表示一个数据,是计算机的最小存储单元 ...
- 3_PHP表达式_5_数据类型转换_类型强制转换
以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. PHP类型转换分为类型自动转换和类型强制转换. 3.5.2 类型强制转换 类型强制转换允许编程人员手动将变量的数据 ...
- MySQL高级查询与编程笔记 • 【第2章 数据定义和操作】
全部章节 >>>> 本章目录 2.1 数据定义语言和数据操作语言 2.1.1 设计"优乐网"数据库 2.1.2 数据定义语言 2.1.3 数据操作语言 ...
- 应用C#和SQLCLR编写SQL Server用户定义函数
摘要: 文档阐述使用C#和SQLCLR为SQL Server编写用户定义函数,并演示用户定义函数在T-SQL中的应用.文档中实现的 Base64 编码解码函数和正则表达式函数属于标量值函数,字符串分割 ...
- 《剑指Offer》题四十一~题五十
四十一.数据流中的中位数 题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中 ...
- Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上)
Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上) 网络嗅探,是监听流经本机网卡数据包的一种技术,嗅探器就是利用这种技术进行数据捕获和分析的软件. 编写嗅探器,捕获数据是前置功能, ...
- [.net 面向对象编程基础] (4) 基础中的基础——数据类型转换
[.net面向对象编程基础] (4)基础中的基础——数据类型转换 1.为什么要进行数据转换? 首先,为什么要进行数据转换,拿值类型例子说明一下, 比如:我们要把23角零钱,换成2.30元,就需要把整形 ...
- 全国计算机等级考试二级教程-C语言程序设计_第14章_结构体、共用体和用户定义类型
函数的返回值是结构体类型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> struct ...
随机推荐
- linux开启远程访问端口
开启3306端口的tcp访问权限 /sbin/iptables -I INPUT -p tcp -dport 3306 -j ACCEPT 保存防火墙信息 /etc/rc.d/init.d/iptab ...
- ORM,DAO,MVC,POJO
1.ORM 对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间 ...
- 当mysql 遇到 ctrl+c
目的 为了理解MySQL在执行大SQL时,对执行CTRL+C产生的疑惑,本文通过实验测试和源码分析两个方面,对MySQL处理CTRL+C的详细过程进行分析和讲解,从而解除DBA及开发人员对CTRL+C ...
- word2vec 中的数学原理二 预备知识 霍夫曼树
主要参考: word2vec 中的数学原理详解 自己动手写 word2vec 编码的话,根是不记录在编码中的 这一篇主要讲的就是霍夫曼树(最优二叉树)和编码. ...
- Linux磁盘空间扩容(LVM)
Linux磁盘空间扩容(lvm) 随着系统的运行时间增长,业务数据的增长,原有磁盘的空间会存在空间不足情况,导致系统不能正常运行,或者系统管理员磁盘没有完全划完,根据使用者的需求自行划分.那么怎么才能 ...
- Angular 5项目
Angular 5项目 如果您正在使用angular, 但是没有好好利用angular cli的话, 那么可以看看本文. Angular CLI 官网: https://github.com/angu ...
- QT5 QSS
设计Qt程序Ui的时候,可以像WEB端使用CSS一样,使用QSS,使页面美化跟代码层分开,利于维护. 过程如下: 1.建立文本文件,写入样式表内容,更改文件后缀名为qss: 2.在工程中新建资源文件* ...
- jQuery选择器(转)
原文:http://www.cnblogs.com/qinwang913/p/3444135.html 一.基本分类 jQuery选择器大致可以分为两类,基本选择器和过滤选择器,总体结构体系如下: ...
- webpack+vue-cli中代理配置(proxyTable)
在做vue的项目时,用到webpack打包工具,我们会发现本地开发开启的node服务地址请求接口的地址存在跨域问题.本地开启的服务地址是 http://localhost:8080 而服务器的地址是 ...
- php模板引擎之featherview
在纯php文件中不加php结束符是一个好习惯,php结束符仅用于在php与html混写时标示php代码结束. <? ?>是短标签,<?php ?>是长标签,在php的配置文件( ...