迈克老猫
来自:老猫的理想
本教程参考C#和ASP.NET程序设计教程撰写,有什么不足之处请大家指出,或在老猫的理想BLOG留言。
这次我们首先讲解一下类型转换,我们在写程序时经常用到类型转换,而且特别多的规则。我在这里粗略的讲解一下。
隐式转换是系统默认的、不需要加以声明即可进行的转换。
1.隐式数值转换
隐式数值转换实际上就是从低精度的数值类型转换到高精度的数值类型的转换。
byte x=255;ushort y=x;y=65535;float z=y;//均从低精度到高精度,反之会产生溢出
隐式数值转换的类型太多,我就不多介绍,记住上面的原则就可以了。详细规则可查看msdn
2.隐式枚举转换
隐式枚举转换用于把十进制整数0转换成任何枚举类型,对应的其他整数则不存在这种转换。
using System;
enum Color
{
Red,Green,Blue
};
class MikeCat
{
static void Main()
{
Color c;//声明Color的变量c;
c=0;//将0转换为Red;
Console.WriteLine("c的值是{0}",c);//结果:c的值是Red;如果将c=0改成c=1,则编译器会给出错误。
}
}
3.隐式引用转换
从任何引用类型到object的转换。
从类类型A到类类型B的转换,其中类A从类B派生得到。
从类类型A到接口类型B的转换,其中类A实现了接口B。
从接口类型A到接口类型B的转换,其中接口A是从接口B派生。
从任何数组类型到System.Array的转换。
从任何委托类型到System.Delegate的转换。
从任何数组类型或委托类型到System.ICloneable的转换。
从空类型(null)到任何引用类型的转换。
显示转换也称为强制转换,它需要用户明确地指定转换的类型。
char c=(char)65;//A
int i=(int)'A';//65
显示转换包含所有的隐式转换,即任何系统允许的隐式转换写成显示转换的形式都是允许的。
int i=300;
long l=(long)i;
另外一例:
using System;
class MikeCat
{
static void Main()
{
long longValue = Int64.MaxValue;
int intValue = (int) longValue;
Console.WriteLine("(int){0} = {1}", longValue, intValue);
}
}
类型 long 转换为 int 是显式转换,它使用了强制转换表达式。输出为:
(int) 9223372036854775807 = -1这是因为有溢出发生。
1.显示数值转换
显示数值转换是指当不存在相应的隐式转换时从一种数值类型转换为另一种数值类型。转换类型也很繁琐,只需记住转换规则,详细查阅MSDN。由于显示数值转换可能丢失信息或引发异常,因此转换按以下原理被处理:简略说就是高精度显示转换为低精度会引发异常(OverFlowException),未引发异常的情况,源变量的值通过舍入得到最接近的整型值作为转换结果。详细转换时的异常情况查阅MSDN
/*test.cs*/
using System;
public class MikeCat
{
public static void Main()
{
ushort u=65535;
byte b=(byte)u;
Console.WriteLine("b的值是{0}",b);
}
}
编译状况如下:
E:\>csc test.cs
Microsoft (R) Visual C# .NET 编译器版本 7.10.3052.4
用于 Microsoft (R) .NET Framework 版本 1.1.4322
版权所有 (C) Microsoft Corporation 2001-2002。保留所有权利。
E:\>test.exe
b的值是255
E:\>csc/checked test.cs ///checked[+|-] 生成溢出检查
E:\>test.exe
未处理的异常: System.OverflowException: 算术运算导致溢出。
at MikeCat.Main()
E:\>csc/checked- test.cs
E:\>test.exe
b的值是255
2.显示枚举转换
显示枚举转换其实就是将枚举类型的元素类型与相应类型之间进行隐式显示转换。比如,有一个元素类型int的枚举类型E,当执行从E到byte的显示枚举转换时,实际执行的是从int到byte的显示数值转换。
using System;
enum Color
{
Red,Green,Blue
};
public class MikeCat
{
static void Main()
{
Color c;//声明Color的变量c;
c=(Color)4;//对数字3进行显示枚举转换
Console.WriteLine("c的值是{0}",c);
}
}
结果:c的值是4
Convert 类
将一个基本数据类型转换为另一个基本数据类型。
该类返回值与指定类型的值等效的类型。受支持的基类型是 Boolean、Char、SByte、Byte、Int16、Int32、Int64、UInt16、UInt32、UInt64、Single、Double、Decimal、DateTime 和 String。
存在将每个基类型转换为每个其他基类型的转换方法。不过,所执行的实际转换操作分为三类:
从某类型到它本身的转换只返回该类型。不实际执行任何转换。
无法产生有意义的结果的转换引发 InvalidCastException。不实际执行任何转换。下列转换会引发异常:从 Char 转换为 Boolean、Single、Double、Decimal 或 DateTime,以及从这些类型转换为 Char。下列转换会引发异常:从 DateTime 转换为除 String 之外的任何类型,以及从任何类型(String 除外)转换为 DateTime。
任何基类型(上面描述的基类型除外)都可以与任何其他基类型进行相互转换。
如果数字类型转换导致精度丢失(即某些最低有效位丢失),不引发异常。但是,如果结果超出了特定转换方法的返回值类型所能表示的范围,则将引发异常。
下面介绍一下和类型转换相关的装箱、取消装箱
装箱是值类型到 object 类型或到该值类型所实现的任何接口类型的隐式转换。将一个值的值装箱会分配一个对象实例并将该值复制到新的对象中。
请看以下值类型变量的声明:
int i = 123;
以下语句对变量 i 隐式应用装箱操作:
object o = i;
此语句的结果是在堆栈上创建对象 o,而该对象在堆上引用 int 类型的值。该值是赋给变量 i 的值类型值的一个副本。下图说明了两个变量 i 和 o 之间的差异。
装箱转换
在堆栈上 在堆上
i 123
int i=123;
o (将i装箱)
object o=i; int 123
也可以(但绝不必要)如下例所示显式执行装箱:
int i = 123;
object o = (object) i;
示例
此例将整数变量 i 通过装箱转换为对象 o。这样,存储在变量 i 中的值就从 123 更改为 456。此例显示对象保留了内容的原始副本,即 123。
// boxing.cs
// Boxing an integer variable
using System;
class TestBoxing
{
public static void Main()
{
int i = 123;
object o = i; // Implicit boxing
i = 456; // Change the contents of i
Console.WriteLine("The value-type value = {0}", i);
Console.WriteLine("The object-type value = {0}", o);
}
}
输出
The value-type value = 456
The object-type value = 123
取消装箱
取消装箱是从 object 类型到值类型或从接口类型到实现该接口的值类型的显式转换。取消装箱操作包括:
检查对象实例,确保它是给定值类型的一个装箱值。
将该值从实例复制到值类型变量中。
以下语句同时说明了装箱和取消装箱操作:
int i = 123; // A value type
object box = i; // Boxing
int j = (int)box; // Unboxing
下图显示了以上语句的结果。
取消装箱转换
在堆栈上 在堆上
i 123
int i=123;
o (将i装箱)
object o=i; int 123
j 123
int j=(int) o;
为使到给定值类型的取消装箱转换在运行时取得成功,源参数的值必须是对某个对象的引用,而该对象先前是通过将该值类型的值装箱创建的。如果源参数为 null 或是对一个不兼容对象的引用,则会引发 InvalidCastException。
示例
下面的示例阐释无效取消装箱的情况,即错误的取消装箱如何导致 InvalidCastException。通过使用 try 和 catch,发生错误时会显示错误信息。
using System;
public class UnboxingTest
{
public static void Main()
{
int intI = 123;
// Boxing
object o = intI;
// Reference to incompatible object produces InvalidCastException
try
{
int intJ = (short) o;
Console.WriteLine("Unboxing OK.");
}
catch (InvalidCastException e)
{
Console.WriteLine("{0} Error: Incorrect unboxing.",e);
}
}
}
输出
System.InvalidCastException
at UnboxingTest.Main() Error: Incorrect unboxing.
如果将下列语句:
int intJ = (short) o;
更改为:
int intJ = (int) o;
转换将执行,而您将得到输出“Unboxing OK”。