[C#] as 和 is 运算符以及安全的类型强制转换
来源:互联网 发布:淘宝所有虎扑推荐店铺 编辑:程序博客网 时间:2024/05/17 01:32
根据MSDN的说明:由于对象是多态的,因此基类类型的变量可以保存派生类型。若要访问派生类型的方法,需要将值强制转换回该派生类型。不过,在这些情况下,如果只尝试进行简单的强制转换,会导致引发 InvalidCastException 的风险。鉴于这个过程是不安全的,因此需要用 try - catch 语句块来进行保护,例如比较安全的代码方式应该如下所示:
但是如上的写法在C#中已经属于过时的写法,而且也属于比较低效的写法。但是类似的转换会经常发生,为了避免异常导致的低效和代码的不简洁,C# 提供 is 和 as 运算符来进行转换。可以使用这两个运算符来测试强制转换是否会成功,而没有引发异常的风险。
一、is 运算符
is 运算符检查对象是否与给定类型兼容。例如,if ( obj is MyObject ) 将检查对象 obj 是否为 MyObject 类型的一个实例,或者是从 MyObject 派生的一个类型的实例。
对于is表达式的结果应该这么看待:如果所提供的对象(表达式)非空,并且可以被强制转换为所提供的类型而不会引发异常,则is表达式的结果就为true,否则为false。
通常使用is表达式的情况是程序运行时才计算类型兼容性,如果已知表达式的值始终为true或者fale,将会导致编译时的警告。
注意:is运算符只考虑引用转换、装箱转换和拆箱转换,不考虑其他转换(包括用户定义的转换)。例如虽然int和double是类型兼容的,但是使用is运算符的结果却是false。
其他需要注意的:
- 不能重载is运算符;
- 在is运算符左侧不允许使用匿名方法(Lambda表达式例外)。
二、as 运算符
as 运算符用于在兼容的引用类型之间执行类似于强制类型转换的操作。与强制类型转换不同的是,如果无法进行转换,as运算符将返回null而不是引发异常。
语法:
expression as type
等效于:
expression is type ? (type) expression : (type) null
注意:as 运算符只能执行引用转换和装箱转换,不能执行拆箱转换(应使用is运算符判断配合强制类型装换来完成),也不能执行其他转换,如用户定义的转换(这类转换应该首先需要相应类型提供转换函数并使用强制转换表达式来完成,或者使用case语句等其他方法来执行)。下面举例说明:
2.1 不能使用 as 运算符进行拆箱转换
即 as 运算符不能应用在值类型数据,如下写会出现编译错误:
object objTest = 11;
正确的写法是:使用is操作符,再加上显式的类型转换操作,就可以安全完成转换,例如:
object objTest = 11;
2.2 不能使用 as 运算符完成用户定义的转换
要想使用户定义的转换操作能正确完成,需要在原类型中增加类型转换操作符函数,例如:
public class NewTypeOne
{
public static explicit operator NewTypeTwo( NewTypeOne objTypeOne )
{
//Convert object into new type
}
}
并使用如下强制类型转换(不能使用 as 运算符):
NewTypeOne
NewTypeTwo newTestTwo = (NewTypeTwo)newTestOne;
2.3 对 as 运算符使用可空类型
允许使用 as 运算符完成基本数据类型(已知值类型)之间的转换,但是由于使用 as 运算符可能产生null值,应注意可能需要对 as 运算符使用 nullable 类型,否则同样可能抛出异常。
下面是摘自MSDN的代码:
void UseAsWithNullable(System.ValueType val)
三、as 运算符和 is 运算符的效率比较
通常,as 运算符更高效一些,因为如果可以成功进行强制转换,它会实际返回强制转换值。而 is 运算符只返回一个布尔值,可能在表达式为true时,还需要进行显示的转换,就需要执行两次类型兼容检查,例如:
而使用as运算符,可以改写为:
对比两种方式,is 需要做两次对象的类型检查;而 as 需要做一次对象类型检查,再加一次null的检查,但是null检查的开销比对象类型检查少,因此相对来说,as的方法效率高些。当然,只是检测类型是否相符那么只用is就可以了,如果要进行类型转化可以直接用as。
四、类型转换总结
综上所述,那么在进行类型转换的时候,可以按照如下的方式进行选择。
用户定义类型之间转换
基本数据类型之间转换
其他类型转换相关:
1. 任何类型都可以转换为其基类类型,用隐式转换即可完成;
2. 任何类型转换为其派生类型时,必须进行显示转换。如:(类型名)对象名;
3. 使用 GetType 可以取得任何对象的精确类型;
4. 基本数据类型是都是已知的值类型,可以使用 Convert 类实现类型转换;
5. 除了 string 以外的其他类型都有 Parse 方法,用于将字符串类型转换成对应的基本类型;
6. 值类型和引用类型的转换称为装箱(boxing)或拆箱(unboxing)。(根据MSDN编程指南:装箱是将值类型转换为object类型或由此值类型实现的任一接口类型的过程。当CLR对值类型进行装箱时,会将该值包装到System.Object内部,再将后者存储在托管堆上。取消装箱将从对象中提取值类型。)
参考:
1. 如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南). MSDN. http://msdn.microsoft.com/zh-cn/library/cc488006
2.
3. is(C#参考). MSDN. http://msdn.microsoft.com/zh-cn/library/scekt9xw
4. C# 中 as 和 is 的用法.
5. C# as 与 is. http://blog.csdn.net/pengfeixiong/article/details/7409875
- [C#] as 和 is 运算符以及安全的类型强制转换
- [C#] as 和 is 运算符以及安全的类型强制转换
- 强制类型转换和as运算符的区别
- C#中的AS、IS运算符与强制类型转换
- 3、强制类型转换、as和is
- C#的as, is和类型强制转换
- 读书笔记之C#的is和as操作符强制类型转换
- 读书笔记之C#的is和as操作符强制类型转换收藏
- as和()强制类型转换的区别
- as和强制类型转换的区别
- 复习试题:运算符以及类型的强制转换
- C#下的强制类型转换应用分析:()、is、as
- 【C++】强制类型转换运算符
- 【C++】强制类型转换运算符的重载
- 使用反射查询类的方法和字段以及使用IS运算符号类转换和AS运算符
- 运算符和强制类型转换
- 运算符和类型强制转换
- C#is 和as运算符
- 时态分析之轨迹追踪
- 命令行运行jar
- 计算机是如何启动的?
- 关于进程间通信的学习心得
- DLNA使用设置教程
- [C#] as 和 is 运算符以及安全的类型强制转换
- asp.net的母版页使用
- Sqlite 学习笔记(一)
- BZOJ3444: 最后的晚餐
- Cracking the coding interview--Q8.6
- MFC关于Radio按钮的操作
- 百度推送的那点事
- osgmotionblur例子
- VS2010/VS2012 重新编译问题