第四课:类型转换

类型之间的转换是经常发生的。比如,你需要去确定一个Integer是否比一个Double大或小。你需要把一个Double 型的数据传入一个以Integer 做参数的方法中。或你可能需要以文本的方式显示数据。

 

上完此课你将会知道:

类型之间的转换.

解释什么是装箱及为什么它应被避免.

实现转换操作符

C#中的转换

C# 禁止丧失精确度的隐形转换。如果目标类型能够容纳所有源类型可能的数据,那么C#允许隐性转换。这被称作一个扩展转换,如下显示:

int i = 1;

double d = 1.0001;

d = i; // Conversion allowed.

如果源类型的范围或精确度超越目标类型,这个操作被称为收缩转换,一般要求显示转换。

1-7 列出执行显示转换的方法:

System Type                 C#                         Converts

System.Convert                             实现了System.IConvertible 接口的类型

                 (type)cast operator 定义了转换操作符的类型之间

 

type.ToString,

type.Parse                               在字符串与基类型相互转换,如果转换不成功就抛异常

 

type.TryParse,                            

type.TryParseExact                              字符串转换为其它基类型,如果转化不成功就返回false

 

 

TryParse, TryParseExact, and TryCast 是在NET 2.0的新方法. 以前的版本中,你必须用parsing conversion 去转换,然后转换失败后还有捕捉异常。如果源类型超过了目标类型的范围或两种类型之间的转换并没有定义,狭窄转换将会失败,所以你应当使用Try块包装一个狭窄转换或使用TryCastTryParse同时检验返回值。

什么是装箱和拆箱?

装箱是把一个值类型转换为一个引用类型,并且拆箱是把一个引用类型转换为一个值类型。以下的例子是把一个Integer类型(值类型)转换为一个Object类型(引用类型)。

int i = 123;

object o = (object) i;

如果你要把一个引用的对象付给一个值类型,拆箱就会发生。以下的例子展示了拆箱:

object o = 123;

int i = (int) o;

装箱和拆箱会引发资源的消耗,所以当编写重复任务的时候,你应当避免装拆箱。如,当你调用继承的结构的方法,同时这个方法是结构继承的System.Object中的虚方法,如ToString。以下的条款是去避免不必的装箱:

实现多个特定类型版本的方法(overloads),使它能够接受不同的值类型。创建overloaded 方法比接受一个Object 变量的方法要好。

只要有可能不用Object 参数,就不要用,用泛型就行了。

当定义结构的时候要Override ToString, Equals, and GetHash 虚成员

如何实现自定义类型的转换

你能用几种方法去定义你自己创建的类型的转换。你选择哪种方法依赖于你想要转换的类型。

Define conversion operators to simplify narrowing and widening conversions

between numeric types.

定义转换操作符(operator)去简化数字类型之间的狭窄和扩展转换。

Override ToString 方法去提供转换到字符串的方法,并且override Parse 方法去把字符串转换为其它类型。

实现接口System.IConvertible 使能通过System.Convert 去做类型转换。

Implement a TypeConverter class to enable design-time conversion for use in the

Visual Studio Properties window. Design-time conversion is outside the scope of

the exam and the TypeConverter class is not covered in this book.

要想看更多的关于design-time conversion, 请看 Extending Design-Time Support

http://msdn2.microsoft.com/en-us/library/37899azc(en-US,VS.80).aspx.

定义类型转换操作符允许你直接地从一个值类型转化为一个自定义类型。使用implicit关键字会使转换不丢掉精确度;使用 explicit 关键字会使转换丢掉精确度

例如,以下的结构定义了允许你在TypeAint直接相互转换:

struct TypeA

{

public int Value;

// Allows implicit conversion from an integer.

public static implicit operator TypeA(int arg)

{

TypeA res = new TypeA();

res.Value = arg;

return res;

}

// Allows explicit conversion to an integer

public static explicit operator int(TypeA arg)

{

return arg.Value;

}

// Provides string conversion (avoids boxing).

public override string ToString()

{

return this.Value.ToString();

}

}

以上的类型也overrideToString方法去做字符串转换而不用装箱。现在你能把一个integer直接转换为这个struct类型,如下所示:

TypeA a; int i;

// Widening conversion is OK implicit.

a = 42; // Rather than a.Value = 42

// Narrowing conversion must be explicit.

i = (int)a; // Rather than i = a.Value

Console.WriteLine("a = {0}, i = {0}", a.ToString(), i.ToString());

 

为了实现System.IConvertible接口,加入IConvertible接口到类型定义中。然后使用Visual Studio去自动地实现这个接口。Visual Studio会插入17个方法的声明,包括为每个基本类型的GetTypeCodeChangeTypeToType方法。你不必实现每个方法,并且其中的一些可能也是无效的比如ToDateTime方法。对于无效的方法,简单地抛出一个异常就可以了,Visual Studio会自动向你没有实现的任何转换方法的代码中加入抛出异常。在你实现了IConvertible接口后, 自定义类型能够使用标准的System.Convert 类去转换类型。如下:

TypeA a; bool b;

a = 42;

// Convert using ToBoolean.

b = Convert.ToBoolean(a);

Console.WriteLine("a = {0}, b = {1}", a.ToString(), b.ToString());

Posted on 2009-09-15 16:11  Sean(陈阳)  阅读(316)  评论(0编辑  收藏  举报