[你必须知道的.NET] 第一回:恩怨情仇:is和as

发布日期:2007.4.7 作者:Anytao

©2007 Anytao.com 转贴请注明出处,留此信息。

 

本文将介绍以下内容:

• 类型转换

• is/as操作符小议 

1. 引言 

类型安全是.NET设计之初重点考虑的内容之一,对于程序设计者来说,完全把握系统数据的类型安全,经常是力不从心的问题。现在,这一切已经在微软大牛们的设计框架中为你解决了。在.NET中,一切类型都必须集成自System.Object类型,因此我们可以很容易的获得对象的准确类型,方法是:GetType()方法。那么.NET中的类型转换,应该考虑的地方有那些呢?

2. 概念引入

类型转换包括显示转换和隐式转换,在.NET中类型转换的基本规则如下:

  • 任何类型都可以安全的转换为其基类类型,可以由隐式转换来完成;
  • 任何类型转换为其派生类型时,必须进行显示转换,转换的规则是:(类型名)对象名;
  • 使用GetType可以取得任何对象的精确类型;
  • 基本类型可以使用Covert类实现类型转换;
  • 除了string以外的其他类型都有Parse方法,用于将字符串类型转换为对应的基本类型;
  • 值类型和引用类型的转换机制称为装箱(boxing)和拆箱(unboxing)。

3. 原理与示例说明

浅谈了类型转换的几个普遍关注的方面,该将主要精力放在is、as操作符的恩怨情仇上了。类型转换将是个较大的话题,留于适当的时机讨论。

is/as操作符,是C#中用于类型转换的,提供了对类型兼容性的判断,从而使得类型转换控制在安全的范畴,提供了灵活的类型转换控制。

is的规则如下:

  • 检查对象类型的兼容性,并返回结果,true或者false;
  • 不会抛出异常;
  • 如果对象为null,则返回值永远为false。

其典型用法为:

 1object o = new object();
 2
 3class A
 4
 5{
 6
 7}

 8
 9if (o is A)  //执行第一次类型兼容检查
10
11{
12
13  A a = (A) o;  //执行第二次类型兼容检查
14
15}

16
17

 as的规则如下:

  • 检查对象类型的兼容性,并返回结果,如果不兼容就返回null;
  • 不会抛出异常;
  • 如果结果判断为空,则强制执行类型转换将抛出NullReferenceException异常。

其典型用法为: 

 1object o = new object();
 2
 3class B
 4
 5{
 6
 7}

 8
 9B b = o as B;  //执行一次类型兼容检查
10
11if (b != null)
12
13{  
14
15  MessageBox.Show("b is B's instance.");
16
17}

18
19

4. 结论

纵上比较,is/as操作符,提供了更加灵活的类型转型方式,但是as操作符在执行效率上更胜一筹,我们在实际的编程中应该体会其异同,酌情量才。 

参考文献

(USA)Jeffrey Richter, Applied Microsoft .NET Framework Programming

 (USA) Stanley B. Lippman, C# Primer

 

©2007 Anytao.com 转贴请注明出处,留此信息。

本贴子以现状提供且没有任何担保,同时也没有授予任何权利。
This posting is provided "AS IS" with no warranties, and confers no rights.

posted @ 2007-04-07 16:57 Anytao 阅读(31275) 评论(111) 编辑 收藏

 回复 引用 查看   
#1楼 2007-04-07 17:09 随风流月      
"除了string以外的其他类型都有Parse方法,用于将基本类型转换为字符串类型"
这一句好像反了,应该是将字符串类型转换为基本类型。感谢您的分享!

 回复 引用 查看   
#2楼[楼主] 2007-04-07 17:17 Anytao      
@随风流月
呵呵,及是,马上修改。

 回复 引用 查看   
#3楼 2007-04-07 19:23 Artech      
@随风流月
除了string以外的其他类型都有Parse方法?应该是“其他的Primitive Type”吧

 回复 引用 查看   
#4楼 2007-04-07 19:37 Artech      
“as操作符在执行效率上更胜一筹”,我觉得比较准确的说法是利用as模式比is模式具有更好的性能,毕竟is和as两个操作符本身不具有可比性。因为采用as模式只进行一个类型的验证,而is模式则会进行两次。
 回复 引用 查看   
#5楼 2007-04-07 20:51 壮志      
http://book.csdn.net/bookfiles/295/10029512570.shtml
这个里面也有一些分析的

 回复 引用 查看   
#6楼 2007-04-07 23:02 布尔      
常用于访问通用对象缓存情况下,如
Person p = new Person()

session["keyName"] = p;
Person p = session["keyName"] as Person;

cache.Add("keyName", p)
Person p = cache.Get("keyName") as Person;

 回复 引用 查看   
#7楼[楼主] 2007-04-07 23:52 Anytao      
@Artech
对,这么表达应该更合适。

 回复 引用 查看   
#8楼[楼主] 2007-04-07 23:56 Anytao      
@壮志
谢谢,值得进一步研究

 回复 引用 查看   
#9楼[楼主] 2007-04-08 00:00 Anytao      
@布尔
对,其实,对象转型的情况下,都可以考虑以as模式类判断,否则应该进行异常处理。

 回复 引用 查看   
#10楼 2007-04-08 12:27 Artech      
@Anytao
异常处理是最不应该推荐的方法,这种方法的性能将会非常地差。

 回复 引用 查看   
#11楼[楼主] 2007-04-08 13:25 Anytao      
@Artech
异常处理是有性能损失,但是对可以预见的异常发生,我的理解是以性能换稳定,as模式中我们就可以捕捉NullReferenceException异常来处理,我觉得更加妥当。

 回复 引用   
#12楼 2007-04-08 14:09 zhuispeed[未注册用户]
effective c# 里面也有一个item是讲这个问题的,按照里面的意思是 尽量使用as ,:)
 回复 引用   
#13楼 2007-04-08 16:34 duanxingchuan[未注册用户]
你好,我想请教一个问题。
在.net环境写的程序,怎样在没有装.net的机子上运行?就是客户机不装.net环境。更简单的说,就是如何把.net程序转换成win32程序。
非常感谢!!!!
若方便的话,可以给我发email:17look@163.com 或 qq: 624611400 .
谢谢大家了!!!!!!!!!

 回复 引用 查看   
#14楼[楼主] 2007-04-08 20:38 Anytao      
@zhuispeed
谢谢提醒,以后有时间看看

 回复 引用 查看   
#15楼 2007-04-09 13:33 Artech      
@Anytao
当然Exception Handler就像是给Application上了个保险。我的意思是尽量预测出现类不能兼容的情况,尽可能不要让Exception Handler起作用。
有这样一个原则:不到万不得已,不要把抛出Exception作为一种运行的条件来设计你的程序。

 回复 引用 查看   
#16楼 2007-04-09 13:37 Artech      
@duanxingchuan
我们一般通过.NET编写的托管的程序,托管程序的执行必须有个托管的执行环境,也就是必须加载CLR,所以托管程序在没有.NET,也就是没有安装.NET Framework(CLR + FCL)的环境中是不能执行的。

 回复 引用 查看   
#17楼 2007-04-09 16:49 阿齐      
@duanxingchuan
看看http://www.remotesoft.com/,其中的Salamander工具--据其介绍,可以生成本地代码(但是我没试过,嘿嘿)

 回复 引用 查看   
#18楼[楼主] 2007-04-10 13:07 Anytao      
@Artech
所言甚是,异常处理最重要的是预见可能出现的异常,这样对性能对安全都是应该的。

 回复 引用   
#19楼 2007-04-11 16:27 wqxh[未注册用户]
大概意思讲了,但是不够详细。
可以参考Effective C#,我觉得那里讲得最详细。

 回复 引用 查看   
#20楼 2007-04-26 22:31 宋欢.net      
Effective C#这本书怎么样呢?
 回复 引用 查看   
#21楼 2007-04-26 23:22 阿齐      
回:Effective C#这本书怎么样呢?
答:这本书很烂

 回复 引用 查看   
#22楼[楼主] 2007-05-25 00:08 Anytao      
@wqxh
希望受用

 回复 引用 查看   
#23楼[楼主] 2007-05-25 00:10 Anytao      
@Sean(陈阳)
@宋欢.net
@阿齐
这本书我没有研读过,大家都提到,可以找时间看看, Effective C++倒是看过,确实是经典。至于Effective C#,还是有时间再来讨教。

 回复 引用 查看   
#24楼 2007-05-25 15:54 周奔驰      
标题党,看不出is和as 有何深仇大恨
 回复 引用 查看   
#25楼[楼主] 2007-05-25 16:52 Anytao      
@周奔驰
不是标题党,是内容党,以内容和观点说话,标题只是个摆设.

 回复 引用 查看   
#26楼 2007-06-22 14:00 steven-chen      
不错,学习了!
 回复 引用   
#27楼 2007-07-11 09:26 pinty[未注册用户]
学习~_~
 回复 引用 查看   
#28楼[楼主] 2007-07-11 13:10 Anytao      
@steven-chen
谢谢关注.

 回复 引用 查看   
#29楼[楼主] 2007-07-11 13:10 Anytao      
@pinty
一起进步.

 回复 引用 查看   
#30楼[楼主] 2007-07-11 13:11 Anytao      
@念时
谢谢关注,继续努力。

 回复 引用   
#31楼 2007-07-17 10:15 doll-net
is 和 as 的用处在某种程度上讲是不挨边的
is 是判断可否将一种类型当作另一种类型使
as 是将一种类型转为另一种类型,转换失败则返回null
就是从你的文章里我也看不出is 和 as有啥恩怨情仇~~~~

 回复 引用 查看   
#32楼 2007-07-18 18:11 脚印      
as 为类型转换,但是他要求转换以后的类型为引用类型(不晓得是否正确)

int a = 1;
object b=a;
int c = b as int //这里就会提示错误2 as 运算符必须与引用类型一起使用(“int”是值类型)


如果这样的话是不是说 as 只能用与

class A
{
.....
}
A a = new a();
object b=a;
A c= b as A;


 回复 引用 查看   
#33楼[楼主] 2007-08-14 08:55 Anytao      
@doll-net
某种程度上,is和as是可以拿出来比较,作为类型转换中的一种常用的手段,注意什么,推荐什么,这是本文的主题。
在此强调的是类型安全。

 回复 引用 查看   
#34楼 2007-09-13 15:17 念时      
用as来转换类型是方便了也保证了安全性,而且不用Try catch……
is 和 as 应该说各有各的用处,只看具体情况了

 回复 引用 查看   
#35楼[楼主] 2007-09-13 22:22 Anytao      
@念时
某种意义上,是这样,这也是.NET本身的优点。

 回复 引用 查看   
#36楼 2007-09-15 14:51 镜涛      
更赞同 is用来判断,as用于转换!
 回复 引用 查看   
#37楼 2007-09-15 18:31 Jacky_xu      
--引用--------------------------------------------------
镜涛: 更赞同 is用来判断,as用于转换!
--------------------------------------------------------
同意

 回复 引用 查看   
#38楼[楼主] 2007-09-16 00:04 Anytao      
@镜涛
@Jacky_xu
不错的补充:-)

 回复 引用 查看   
#39楼[楼主] 2007-09-26 10:49 Anytao      
@chinaifne
:-)

 回复 引用 查看   
#40楼 2007-10-01 03:17 ascliy      
学习,谢谢分享
 回复 引用 查看   
#41楼[楼主] 2007-10-02 10:33 Anytao      
@ascliy
对大家有用就行,实感欣慰。

 回复 引用   
#42楼 2007-12-06 21:23 嘟嘟嘟嘟[未注册用户]
有个疑问
A a = new a();
object b=a;
A c= b as A;

这样的转化跟

A a = new a();
object b=a;
A c= (A)b;

对比,具体有什么区别呢?

 回复 引用 查看   
#43楼[楼主] 2007-12-06 21:51 Anytao      
@嘟嘟嘟嘟

as实现了引用类型的强制转换,不会引发异常,b as A可以等效于:
b is A ? (A)b : null

而显示类型转换不具有该特性,总结其主要区别:

1 as只能操作引用类型;(type)变量名可以应用于值类型和引用类型;
2 as不会引发不兼容类型转换异常,有性能优势;显示类型转换,可能引发异常,不推荐。

 回复 引用   
#44楼 2007-12-07 18:30 嘟嘟嘟嘟 [未注册用户]
原来如此啊,以后要楼主多指教了
 回复 引用 查看   
#45楼[楼主] 2007-12-07 19:32 Anytao      
@嘟嘟嘟嘟
:-), 不敢不敢,我很喜欢讨论,谢谢参与。

 回复 引用   
#46楼 2007-12-20 17:43 zhslsnow[未注册用户]
呵呵,文章很好
只是导航没做好吧?找了很久没发现有到下一回的链接呃~

 回复 引用 查看   
#47楼[楼主] 2007-12-20 17:59 Anytao      
@zhslsnow
你好,这个系列的导航在下述地址:

http://www.cnblogs.com/anytao/archive/2007/09/14/must_net_catalog.html

 回复 引用 查看   
#48楼 2008-01-04 10:13 第4只苹果      
所以本文的推荐是:

A a = new A();
object b = a; //这是隐式,与is 和as 无关

A c= b as A; //这是LZ推荐的引用类型转换机制,对吗?

如果不成功c为null(当然这里是成功的了:))
if(c==null)
{
您打算 throw exception在这里吗?
}

 回复 引用 查看   
#49楼[楼主] 2008-01-04 21:41 Anytao      
@第4只苹果
所言正确,对于c==null是否抛出异常,视具体的情况而定,而抛出异常是通常的选择。



--引用----------------------------------------------
Anytao: @嘟嘟嘟嘟

as实现了引用类型的强制转换,不会引发异常,b as A可以等效于:
b is A ? (A)b : null

而显示类型转换不具有该特性,总结其主要区别:

1 as只能操作引用类型;(type)变量名可以应用于值类型和引用类型;
2 as不会引发不兼容类型转换异常,有性能优势;显示类型转换,可能引发异常,不推荐。
--------------------------------------------------------

b as A可以等效于:
b is A ? (A)b : null 这样的话使用 as 不是一样需要两次兼容检查吗?性能为何会好呢?

 回复 引用 查看   
#51楼[楼主] 2008-05-23 15:40 Anytao      
@玄武湖到西湖
我提到的
------------------------------
b as A可以等效于:
b is A ? (A)b : null
-----------------------------
是对as语义的解释,而非实际的执行过程,实现上你可以从IL的分析或者二者的差别:
object a = new object();
A b = a as A;

if (a is A)
{
A c = (A)a;
}
可以根据其IL进行进一步的分析,即可知执行兼容性检查的本质:-)

 回复 引用 查看   
#52楼 2008-05-27 14:47 agp001      
学习中
 回复 引用 查看   
#53楼[楼主] 2008-05-27 17:50 Anytao      
@agp001
常来常新:-)

 回复 引用   
#54楼 2008-07-30 11:03 yiyisawa.Liu[未注册用户]
楼主的精神值得敬佩,不好意思再潜水了.学习中.
 回复 引用 查看   
#55楼[楼主] 2008-07-31 01:25 Anytao      
@yiyisawa.Liu
呵呵,欢迎常来看看:-)

 回复 引用 查看   
#56楼 2008-08-27 11:40 YITIAN Studio      
程序员都有挑剔和骄傲的情节。
“在.NET中,一切类型都必须集成自System.Object类型”原文中打错字啦,应该是继承。

说实话我不知道为什么总是推荐用哪个,然后说什么好不好,效率什么的。。。就是一个小小的is和as至于影响效率么?
还有真的有把很不相关的两个类用is或者as搞到一起的么。。。
如果按照这样的思路去学语言会不会有点舍本逐末。

ps:我只看了这一篇,并且我自认也是个新手。还请高手回答我的疑虑。谢谢。
from千冰念

 回复 引用 查看   
#57楼[楼主] 2008-08-28 12:38 Anytao      
@YITIAN Studio
首先谢谢你的指正。

关于is和as实质上是两张模式,在实际的系统中对于类型的判定常常是必须的,因为很多时候你并不清楚接受的参数是否是一个兼容的类型,就像你说的一样两个不相关类型的变量是经常会搞到一起的。
非安全的类型参数或者变量会引起系统灾难,这是类型检查存在的意义,也就是is和as存在的意义,一种实现的手段。

 回复 引用 查看   
#58楼 2008-09-15 00:21 michaellu      
受教。
 回复 引用 查看   
#59楼[楼主] 2008-09-18 20:43 Anytao      
@michaellu
~!~

 回复 引用 查看   
#60楼 2008-09-27 11:22 棠棠dotNet      
感谢LZ分享,长期关注支持你的新文章。(:
 回复 引用 查看   
#61楼 2008-10-06 13:15 dream one minute      
谢谢分享,学习中。
 回复 引用 查看   
#62楼[楼主] 2008-10-06 16:48 Anytao      
@棠棠dotNet
呵呵,谢谢你的关注:-)

 回复 引用 查看   
#63楼[楼主] 2008-10-06 16:48 Anytao      
@dream one minute
呵呵,欢迎欢迎:-)

 回复 引用 查看   
#64楼 2008-12-12 09:17 tosun      
请问这句话在表述上是不是有点错误哦,反正我在第一次看的时候没有明白过来。

如果结果判断为空,则强制执行类型转换将抛出NullReferenceException异常。


不知道是不是我还没有理解清楚。正在拜读的你文章中。。。

 回复 引用 查看   
#65楼[楼主] 2008-12-12 17:54 Anytao      
--引用--------------------------------------------------
如果结果判断为空,则强制执行类型转换将抛出NullReferenceException异常。
-------------------------------------------------------
呵呵,写的快了点儿,表达欠妥。如果结果判断为空,强制执行类型转换,相当于对null执行操作,则将抛出NullReferenceException异常。

 回复 引用   
#66楼 2008-12-17 14:52 @chenfeng.tang[未注册用户]
LZ,看了你的文章,解释得很清楚,说得很好!
虽然我是第一次接触C#,不过一看就懂,之前我用的是JAVA,
现在感觉C#跟JAVA几乎没什么大的区别,就同is的用法一样,
JAVA里面用的是 instance of,也是用来判断一个对象是否属于一个类的一个事例的.
呵呵,LZ,有机会得好好向你请教请教啊!

 回复 引用 查看   
#67楼[楼主] 2008-12-20 17:05 Anytao      
@@chenfeng.tang
随时恭候。Java和c#在语言特性上有很多类似,但是也存在不少差别,所以了解差别,兼顾共性,会很好。

 回复 引用 查看   
#68楼 2009-01-12 17:21 赵俊      
看了一下感觉is和as就是用来判断类型是否相同的,我写程序好像都没有用到过,:( 能不能告诉我is和as一般在哪些应用中会用到啊?谢谢。
 回复 引用 查看   
#69楼 2009-01-23 00:30 Done      
请问楼主“任何类型转换为其派生类型时,必须进行显示转换,转换的规则是:(类型名)对象名; ”一个对象能强制转换成它的派生类吗?那这段代码为什么编译不过呢
internal class A
{
//...
}
public sealed class Program
{
public static void Main()
{
object o1 = new object();
A a1 = (A)o1;//把object类型转换成A类型,编译不通过
}
}
什么是类型兼呢,呵呵,谢谢

 回复 引用 查看   
#70楼[楼主] 2009-02-02 08:58 Anytao      
@赵俊
文中已有详细的示例。一般来说,is常做类型兼容检查,而as用来做类型转换:-)

 回复 引用 查看   
#71楼[楼主] 2009-02-02 09:07 Anytao      
@Done
一个对象能强制转换成它的派生类吗?

答案是:能。否则一个违反Liskov替换原则的面向对象语言,何以面见万千程序开发者的颜面:-)

另外,你提供的代码显然是没有问题的,不知为何编译通不过:-)

 回复 引用 查看   
#72楼 2009-03-03 17:34 hhe      
LZ ,你好看了你的文章我有一个疑问:

class a {}
A a = new A();
//object o = new object();
object o =a;

A a1 = o as A;
if (a1==null)
{

}
为什么o=new object()就返回null ,而o=a就不为null
object o=a是不是已经隐士的进行了转换了,new 的为什么不行?

ps: 本人新手

 回复 引用   
#73楼 2009-03-03 18:27 nobodyknow[未注册用户]
@Done
一个对象当然能转换成任何类,引用类型之间的转换,要用as
你用的是啥??是强制类型转换,去看看强制类型转换的使用再说吧

 回复 引用   
#74楼 2009-03-03 18:29 nobodyknow[未注册用户]
@hhe
object o = new object();返回的是null吗???
那o.toString()有怎么解释呢?要知道null.toString()是要砍头的

 回复 引用   
#75楼 2009-03-04 09:34 hazel[未注册用户]
@nobodyknow
砍头,o(>﹏<)o千万别,,我说的是a1 :-)

 回复 引用 查看   
#76楼[楼主] 2009-03-04 11:25 Anytao      
@hhe
@hazel
@nobodyknow
你们的讨论实在太精彩了:-)

基于你的问题,我想还是回到as的规则来了解就一目了然了:

检查对象类型的兼容性,并返回结果,如果不兼容就返回null;
不会抛出异常;
如果结果判断为空,则强制执行类型转换将抛出NullReferenceException异常。

其实A a1 = o as A;时a1是否为null完全取决于类型兼容性检查的结果,你看到的结果也就是类型检查的结果罢了。

 回复 引用 查看   
#77楼 2009-03-05 23:37 anncesky      
--引用--------------------------------------------------
hhe: LZ ,你好看了你的文章我有一个疑问:

class a {}
A a = new A();
//object o = new object();
object o =a;

A a1 = o as A;
if (a1==null)
{

}
为什么o=new object()就返回null ,而o=a就不为null
object o=a是不是已经隐士的进行了转换了,new 的为什么不行?
-------------------------
去看看多态条件

ps: 本人新手
--------------------------------------------------------

 回复 引用 查看   
#78楼 2009-03-12 22:35 会长      
O(∩_∩)O~:
as 运算符必须用于引用类型或可为 null 的类型;
呵呵,补充一点。

 回复 引用 查看   
#79楼[楼主] 2009-03-18 10:36 Anytao      
@anncesky
??你的问题是

 回复 引用 查看   
#80楼[楼主] 2009-03-18 10:48 Anytao      
@会长
很好的补充

 回复 引用   
#81楼 2009-05-05 08:45 LOVE勇
谢谢楼主的技术公开!
 回复 引用 查看   
#82楼[楼主] 2009-05-05 09:42 Anytao      
@LOVE勇
重在参与:-)

 回复 引用   
#83楼 2009-07-06 22:00 Fonlue[未注册用户]
引用Anytao:@Done
<br/>一个对象能强制转换成它的派生类吗?
<br/>
<br/>答案是:能。否则一个违反Liskov替换原则的面向对象语言,何以面见万千程序开发者的颜面:-)
<br/>
<br/>另外,你提供的代码显然是没有问题的,不知为何编译通不过:-)

Liskov替换原则,不是指子类应该能够完全替换父类么?一个父类对象转换为其子类对象,编译通过,但意义又何在呢?会有什么样的应用场景呢?本人初学,望指教 :)

 回复 引用 查看   
#84楼 2009-07-25 11:40 子逸      
is 和 as 作用明显不同, 没有可比性.
建议as前先is判断.

 回复 引用 查看   
#85楼[楼主] 2009-07-27 10:32 Anytao      
@子逸
如果你够清楚,那么可比性之说本来就无从谈起,如果你不够清楚,那么比较比较也有助于认识清楚。

关于as之前先is判断,我觉得倒大可不必,因为as本身就有兼容性检查的过程,大可不必二次轮询。

 回复 引用 查看   
#86楼 2009-09-24 09:54 stargazer      
@Done
@Fonlue
MyBase derivedObject = new MyDerived();
MyBase baseObject = new MyBase();
MyDerived derivedCopy1 = (MyDerived) derivedObject; // OK
MyDerived derivedCopy2 = (MyDerived) baseObject; // Throws exception
上面的代码都是合法的C#代码(从句法的角度来看,是合法的),是把基类转换为派生类。但是,最后的一个语句在执行时会抛出一个异常。在进行数据类型转换时,会检查被引用的对象。因为基类引用实际上可以引用一个派生类实例,所以这个对象可能是要转换的派生类的一个实例。如果是这样,转换就会成功,派生的引用被设置为引用这个对象。但如果该对象不是派生类(或者派生于这个类的其他类)的一个实例,转换就会失败,抛出一个异常。

 回复 引用 查看   
#87楼 2009-10-29 14:55 勇赴      
引用Artech:“as操作符在执行效率上更胜一筹”,我觉得比较准确的说法是利用as模式比is模式具有更好的性能,毕竟is和as两个操作符本身不具有可比性。因为采用as模式只进行一个类型的验证,而is模式则会进行两次。

就单纯的is和as操作符而言,我认为并没有任何性能上差异,你说的as模式和is模式应该是强制类型转换模式,当is为true时还要在if语句中再进行一次这样的[(类型名)对象名]形式的转换, 这时CLR会再次验证类型的兼容性,而as操作符返回的要么是对象的引用,要么是null,这时我们只要判断是否为null就行了,避免了再一次进行类型兼容性检查。

 回复 引用 查看   
#88楼 2009-10-29 15:00 勇赴      
引用子逸:
is 和 as 作用明显不同, 没有可比性.
建议as前先is判断.

完全没必要,as就是为了避免我们在类型转换时的多次类型兼容性检查,你倒好,现在is,as全用,如果是这样,用一个is就OK了,不要用as

 回复 引用 查看   
#89楼 2009-10-29 15:09 勇赴      
引用anncesky:--引用--------------------------------------------------
<br/>hhe: LZ ,你好看了你的文章我有一个疑问:
<br/>
<br/>class a {}
<br/> A a = new A();
<br/> //object o = new object();
<br/> object o =a;
<br/>
<br/> A a1 = o as A;
<br/> if (a1==null)
<br/> {
...

因为as前面的对象要转化为as后面的类型对象,这个对象的类型必须是as后面类型本身或它的子类,而object类型是所有类型的必须直接或间接继承的的根类,所以它只有as它自己的类型才能as成功,哈哈。

 回复 引用 查看   
#90楼 2009-10-29 15:24 勇赴      
引用Done:请问楼主“任何类型转换为其派生类型时,必须进行显示转换,转换的规则是:(类型名)对象名; ”一个对象能强制转换成它的派生类吗?那这段代码为什么编译不过呢<br/>internal class A<br/>{ <br/> //...<br/>}<br/>public sealed class Program<br/>{<br/> public static void Main()<br/> {<br/> object o1 = new object();<br/> A a1 = (A)o1;//把object类型转换成A类型,编译不通过<br/> }<br/>}<br/>什么是类型兼呢,呵呵,谢谢

一个晕字了得,object o1=new object();这里的o1你可以把它看成一个指针,他可以引用所有直接或间接继承自它的类,这里o1指向的是一个object类型的实例,所以你想把这个实例转化为其它类型的变量(指针)是不行的,你可以想象一下,A类型是一个继承自object类的类型,里面如果有实现的话,假如多一个方法public void Func();这时你将一个object实例转换成A类型的实例,假如让你通过转换,这时你调用a1.Func()会成功吗?当然不会,因为object类型中根本没这个方法,当然你object o1=new object();里的o1也不会有,这肯定会出错的。所以我们说类型转换,其实转换不是类型,而是类型实例,就是你的类型变量引用的那个真正的类型实例,如果你用object o1=new A();这时o1引用的就是A类型的一个实例,这时再将o1转换时A a1=(A)o1;就不会出错,因为o1指向的实例正是A类型实例。

 回复 引用 查看   
#91楼 2009-10-30 16:48 半人半兽      
我觉得,is 和 as 本身是没有什么可比性。但是在类型转换时可以用它们来保证类型安全。这应该是这篇文章想要表达的吧。

is 是用来判断能不能做转换,结果为False就不执行转换代码,这样可以保证类型安全。
as 是转换后,转换成功就返回对象,转换失败结果为null,所以通过判断结果是否为null,可以保证类型安全。

 回复 引用 查看   
#92楼 2009-10-31 19:11 勇赴      
引用半人半兽:
我觉得,is 和 as 本身是没有什么可比性。但是在类型转换时可以用它们来保证类型安全。这应该是这篇文章想要表达的吧。

is 是用来判断能不能做转换,结果为False就不执行转换代码,这样可以保证类型安全。
as 是转换后,转换成功就返回对象,转换失败结果为null,所以通过判断结果是否为null,可以保证类型安全。

我一直怀疑微软当初设计is的时候并不是用来做类型转换的用的,只是做类型判断,那做类型判断除了接下来做类型转换我想不出还有什么用?所以如果is除了上面说的作用之外再没有其它的用,可以直接舍弃了,一个as就够了,我觉的。

 回复 引用 查看   
#93楼 2009-10-31 20:03 勇赴      
不过事实不是如此,哈哈。
C#为我们做引用类型的转换提供了一个操作符as,as只能用于引用类型,还有一个用于类型判断的is,is操作符可以即用于值类型也可以用于引用类型。

我开始感觉对:“任何类型转换为其派生类型时,必须进行显示转换,转换的规则是:(类型名)对象名”是理解了!大概就是下面的基类object可以显示转换为派生类int
object obj = "123";
int i = (int)obj;
Console.Write("{0}", i);
但是当我使用继承时,基类(父类)转换为其派生类(子类)时,编译能通过,但运行是会出现未处理InvalidCastException异常,代码如下:
class Animal
{
private float _weight;
public float Weight
{
get { return _weight; }
set { _weight = value; }
}
private int _feet;
public int Feet
{
get { return _feet; }
set { _feet = value; }
}

public void SelfType()
{
Console.Write("My Type is Animal! I have {0} feet and my weight is {1}! ",Feet,Weight);
}
}

class Cat : Animal
{
public void SelfType()
{
Console.Write("My Type is Cat! I have {0} feet and my weight is {1}!",Feet,Weight);
}
}

class Program
{

static void Main(string[] args)
{
Animal a = new Animal();
a.Feet = 2;
a.Weight = 3.4F;

if (a is Animal)
{
Cat c = (Cat)a;
c.SelfType();
}
else
{
Console.Write("My type is not {0}!", a.GetType());
}


}
}

编译没错,但当执行到Cat c = (Cat)a;
时会抛出:未处理InvalidCastException异常,异常信息为无法将类型Animal的对象强制转换为类型Cat。

这让我对此有产出了质疑,理论上来说应该可以显示转换的,那为什么又会异常呢?是不是我理解上出了偏差,还请指教?

 回复 引用 查看   
#95楼 2009-11-30 14:37 承影惆怅      
非常感谢楼主的文章,受益匪浅,不过本人有点疑问,望请楼主不吝指教!
文章中举例:is典型用法为:

1 object o = new object();
2
3 class A
4
5 {
6
7 }
8
9 if (o is A) //执行第一次类型兼容检查
10
11 {
12
13 A a = (A) o; //执行第二次类型兼容检查
14
15 }

例子中if(o is A) 好像一直否会返回false吧?因为o的类型为object!
那如果假设object是类型B的基类的话,是不是应该就是:
if(o is object)
{
B b = (B)o;
}
else
{
console.write("o is null");
}
这样就避免了NullReferenceException异常,但是对B b = (B)o;是不是还可能存在InvalidCastException异常?
这里假设:B为int类型,o被复制为字符串,o="asdf"!
不知道这里InvalidCastException异常是不是只能用try...catch避免呢?

 回复 引用 查看   
#96楼 2010-01-14 09:07 Ryan Boo      
本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利。
This posting is provided "AS IS" with no warranties, and confers no rights.

这些内容是啥意思?

 回复 引用 查看   
#97楼 2010-02-21 15:57 刀奶特      
看了您的文章跟下面的评论,有个效率的问题想问下,例子如下:
string a=string.Empty;
a=obj(object类型) as string;
a=(string)obj;
a=convert.ToString(obj);
a=obj.ToString();
哪个更好些啊,就效率跟安全性而言,希望指教

 回复 引用 查看   
#98楼 2010-05-26 15:38 xia,oYe!      
@勇赴
呵呵 is判断完成后不一定要进行类型转换,比如用接口实现多态的时候,用N多个类型继承一个基类,但每个子类各有差别,有的实现了某个接口,有的没有实现,当你遍历一个包含了N多个子类的基类数组时,遍历每一个元素是否实现某一个接口(用is判断),如果实现了,就调用该方法。书上看的 共同探讨

 回复 引用 查看   
#99楼 2011-02-12 15:46 傅红雪2011      
学习了