As与强制类型转换的区别以及Is运算符的使用
前言:
开发人员经常需要将一个对象从一个类型转换成其他类型。
在c#中,类型转换按照转换方式分类分为了隐式转换和显式转换,按对象分类又分为了值类型转换和引用类型转换
CLR(参考:http://baike.baidu.com/view/605055.htm)允许将一个对象强制转换成它的类型或者是它的任何基类型。每种编程语言都规定了具体如何将转型操作揭示给开发人员。例如C#不需要任何特殊语法即可将一个对象强制转换成它的任何基类型,因为向基类型的转换被认为是一种安全的隐式转换。然而,C#要求开发人将一个对象显式转换成它的任何派生类型,因为这样的转型可能在运行时失败。
using System; namespace ConsoleApplication1 { class C1 { };//该式隐式从System.Object派生 class Program { static void Main(string[] args) { //向基类型转换不需要转型 Object o = new C1(); //向派生类型转换需要转型 C1 c = (C1)o; } } }
参考:http://blog.csdn.net/haoyuan711/article/details/5917806
隐式转换中,基类型不能访问派生类中的特有部分(如上的代码,c2.a不能通过编译),且派生类对象指针不能引用基类对象地址,即容易发生信息丢失,因此C#提供了显示转换(强制转换)
强制转换一般是由精度较高数据向精度较低数据转换或者是父类向子类的转换,一般不会发生信息丢失,但是在强制类型转换的过程中,值类型可能会出现溢出错误,而引用类型的强制类型转换则容易出现类型不兼容的错误。处理方法有两种
1、用try...catch捕获异常
2、用is或是as来检查一个对象是否兼容于其他指定的对象
在C#中使用is和as操作符来进行强制类型转换
MSDN(is操作符):http://msdn.microsoft.com/zh-cn/library/scekt9xw.aspx
using System; namespace ConsoleApplication5 { class Class1 { }; class Class2 { }; class Class3 : Class2 { }; class IsTest { static void Test(object o) { Class1 a; Class2 b; if (o is Class1) { Console.WriteLine("o is Class1"); a = (Class1)o; } else if (o is Class2) { Console.WriteLine("o is Class2"); b = (Class2)o; } else { Console.WriteLine("o is neither Class1 nor Class2"); } } static void Main(string[] args) { Class1 c1 = new Class1(); Class2 c2 = new Class2(); Class3 c3 = new Class3(); Test(c1); Test(c2); Test(c3); Test("string"); Console.ReadKey(); /* Output: o is Class1 o is Class2 o is Class2 o is neither Class1 nor Class2. */ } } }
is操作符检查一个对象是否兼容于指定的类型,并返回一个Boolean值:true或false。
关于is操作符有一下几点说明:
1、is操作符永远不会抛出异常
2、is会核实对象是否兼容于指定类型,对象派生自指定类型称作兼容
class Class2 { }; class Class3 : Class2 { }; class IsTest { static void Test(object o) { Class1 a; Class2 b; Class3 c0 = new Class3(); Console.WriteLine(c0 is Class2); Class2 c1 = new Class2(); Console.WriteLine(c1 is Class3); //结果:True // False
3、is 运算符只考虑引用转换、装箱转换和取消装箱转换。 不考虑其他转换,如用户定义的转换。
PS:用户定义的转换:http://msdn.microsoft.com/zh-cn/library/aa691298(v=vs.71).aspx
http://msdn.microsoft.com/zh-cn/library/aa664464(v=vs.71).aspx
4、is操作符可以检查值类型的兼容性,但仅限于同种类型(返回True),不同类型(例如int和double)则返回False
using System; namespace ConsoleApplication3 { class Program { static void Main(string[] args) { double a = 2; Boolean b1 = a is double; Console.WriteLine(b1);//返回True
5、Is操作符执行类型转换的常用编程模式
if (o is Class1) { Class1 a = (Class1)o;
CLR实际检查了两次对象的类型,is操作符首先核实o是否兼容于Class1类型,如果答案是肯定的,CLR会再次核实o是否引用一个Class1.CLR的类型检查增强了安全性,但无疑也会对性能造成一定影响
AS操作符
as 运算符用于在兼容的引用类型之间执行某些类型的转换
注意,as 运算符只执行引用转换和装箱转换。 as 运算符无法执行其他转换,如用户定义的转换,这类转换应使用强制转换表达式来执行。
AS的工作方式和强制转换一样,只是它永远不抛出异常
using System; namespace ConsoleApplication4 { class ClassA { } class ClassB : ClassA { } class ClassC { } class MainClass { static void Main() { object[] objArray = new object[3]; objArray[0] = new ClassA(); objArray[1] = new ClassB(); objArray[2] = new ClassC(); for (int i = 0; i < objArray.Length; ++i) { ClassA s = objArray[i] as ClassA ; Console.Write("{0}:", i); if (s != null) { Console.WriteLine("兼容于ClassA'"); } else { Console.WriteLine("不兼容于ClassA"); } } Console.ReadKey(); } } } /* Output: 0:兼容于ClassA' 1:兼容于ClassA' 2不兼容于ClassA */
在AS操作符下的常用编程模式:
Class2 c2 = c1 as Class1;
if (c2 != null)
{}
这种编程模式替代了is操作符的类型转换的编程模式,简化了其代码的写法,同时提高了性能
关于AS操作符,有一下几点说明
1、只能对引用类型或者是值可以为null的类型操作
2、不要与is同时使用