C#按类型在内存中的存储方式不同分为:值类型和引用类型。值类型有:基本数据类型、结构和枚举;引用类型有:类、接口、数组和委托。
由于 C# 是在编译时静态类型化的,因此变量在声明后就无法再次声明,由此变量类型就固定了,按照类型存储机制,变量只能在同一类型间相互存储,于是其它类型的变量就不能存储在该类型变量中,除非对其它类型变量进行类型转换。
由于程序功能的需要,不可避免在不同类型变量间赋值或计算,如将整形变量赋值给浮点型变量。下面介绍C# 支持几种类型。
1 隐式转换
如果数据转换不会导致数据丢失,即数据转换是安全的,则由编译器自动进行转换,不需要任何特殊的语法。
一般有从较小整数类型到较大类型的转换、从整数类型到浮点类型的转换、从派生类类型到基类类型的转换。
例如:
int i = 1; float f = i;
2 显式转换
2.1 显式转换概念
显示转换也称为强制转换,对于在转换过程中可能出现数据丢失这种不安全的行为,用户必须显式地指出转换为何种类型,负责编译会报错,其用意为用户应对该种类型转换负责,就是说用户明确转换带来的后果。
一般有从高精度类型到低精度类型的转换、从基类类型到派生类型的转换。
例如:f = 2.3F; i = (int)f;
在有些显示转换的过程中,编译过程不会报错,但在运行时会抛出类型转换异常,而相应的解决机制是使用>class Animal{ public void Eat() { Console.WriteLine("Eating."); } public override string ToString() { return "I am an animal."; }}class Reptile : Animal { }class Mammal : Animal { }class UnSafeCast{ static void Main() { Test(new Mammal()); // Keep the console window open in debug mode. System.Console.WriteLine("Press any key to exit."); System.Console.ReadKey(); } static void Test(Animal a) { // Cause InvalidCastException at run time // because Mammal is not convertible to Reptile. Reptile r = (Reptile)a; }}
Reptile和 Mammal 类同时继承了Animal 类,Test()方法的形参为Animal 对象,由于派生类对象可以隐式转换到基类对象,所以使用Mammal 对象调用 Test()方法时,编译不会报错,但由于Reptile 和Mammal 类仅只是Animal 的派生类,不能相互转换,由此在运行时抛出异常。
2.3 is 和as的使用
> if (newclass is object) { //to do something } else { //to do something }
as关键字用于兼容的引用类型之间进行转换。定义格式如下。
> Mammal m = o as Mammal; if (m != null) { Console.WriteLine(m.ToString()); } else { Console.WriteLine("{0} is not a Mammal", o.GetType().Name); }
通常,as 运算符更高效一些,因为如果可以成功进行强制转换,它会实际返回强制转换值。而>class SampleClass{ public static explicit operator SampleClass(int i) { SampleClass temp = new SampleClass(); // code to convert from int to SampleClass... return temp; }}
4 使用帮助程序类的转换
考虑到有些情况比较常见,如字符串转换到数字,系统特意编写专门用来处理该种类型转换的类,以供用户调用。
常见的有将字节数组转换为int、将字符串转换为数字和在十六进制字符串与数值类型之间转换。
5 参考
C# 编程指南
C# 自学手册