c#之用户定义的数据类型转换介绍
c# 允许用户进行两种定义的数据类型转换,显式和隐式,显式要求在代码中显式的标记转换,其方法是在圆括号中写入目标数据类型。
对于预定义的数据类型,当数据类型转换时可能失败或丢失某些数据,需要显式转换,
1 把int数值转换成short时,因为short可能不够大,不能包含转换的数值。
2 把有符号的数据转换为无符号的数据,如果有符号的变量包含一个负值,会得到不正确的结果。
3 把浮点数转换为整数数据类型时,数字的小数部分会丢失。
此时应在代码中进行显式数据类型,告诉边起义你知道这会有丢失数据的危险,因此编写代码时套把这些可能考虑在内。
c#允许定义自己的数据类型,这意味着需要某些工具支持在自己的数据类型间进行数据转换。方法是把数据类型转换定义为相关类的一个成员运算符,数据类型转换必须声明是隐式或者显式,以说明怎么使用它。
注意:如果源数据值使数据转换失败,或者可能会抛出异常,就应把数据类型转换定义为显式。
定义数据类型转换的语法类似于运算符重载。
例如 :隐式类型转换:
public static implicit operator float(current current)
{
}
和运算符重载相同,数据类型转换必须声明为public和static。
注意:
当数据类型转换声明为隐式时,编译器可以显式或者隐式的调用数据类型转换。
当数据类型转换声明为显式时,编译器只能显式的调用类型转换。
下面是个小例子:
using system;
using system.collections.generic;
using system.linq;
using system.text;
namespace 类型转换
{
struct current
{
public uint dollars;
public ushort cents;
public current(uint dollars, ushort cents)
{
this.dollars = dollars;
this.cents = cents;
}
public override string tostring()
{
return string.format("{0}.{1,-2:00}",dollars,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);
}
}
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 (system.exception ex)
{
console.writeline("exception occurred:" + ex.message);
}
console.readkey();
}
}
}
将涉及到两个问题:
1 从float转换为current得到错误的结果50.34,而不是50.35.----圆整造成的....发生截断问题。
答:如果float值转换为uint值,计算机就会截断多余的数字,而不是去圆整它。计算机中数据是通过二进制存储的,而不是十进制,小数部分0.35不能以二进制形式储存。因为舍弃一部分,故实际转化成的数据要小于0.35,即可以用二进制形式存储的值,然后数字乘以100,得到小于35的数字34.有时候这种阶段是很危险的,避免这种错误的方式时确保在数字转换过程中执行智能圆整操作。
microsoft编写了一个类system.covert来完成该任务。system.covert包含大量的静态方法来执行各种数字转换,我们要使用的是convert.touint16()。注意,在使用system.covert方法会产生额外的性能损耗,所以只有在需要的时候才使用。
注意: system.covert方法还执行他们自己的溢出检查,所以
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);
}
}<span style="font-family: arial, verdana, sans-serif">
</span>