温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C#类型转化需要注意什么

发布时间:2021-12-01 14:17:51 来源:亿速云 阅读:147 作者:小新 栏目:编程语言

这篇文章给大家分享的是有关C#类型转化需要注意什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

1、as和is操作符都不执行任何用户自定义的转换。

2、对于强制转换,引用为空将会转换出错。

3、强制转换任意类型和自定义转换两种情况的IL代码展示有区别。

4、用户自定义转换只作用于对象的编译时类型。

5、as操作符不能应用于值类型。

6、foreach循环语句中使用强制类型转型。

下面我们逐一进行介绍说明:

1,我们先来看错误代码示例:

classA  {   }  classC  {  publicstaticimplicitoperatorA(Ct)  {  returnnewA();  }  }  classProgram  {  staticvoidMain(string[]args)  {  objecto=Factory.GetObject();  //o为一个C类型:  Aa=oasA;//转型失败,o的类型不是A  }  }

代码已经很明显,我们不可以因为定义了C到A的强制转换,就使用as,对应用户自定义转换,我们只可以使用(A)o转换,其实自定义转换和自定义操作=、+、-、"、%等操作符是一样的机理,这样你就明白为什么用as不可以使用自定义转换了。


2,还是看一个错误示例:

classA  {   }  classB:A  {   }  classProgram  {  staticvoidMain(string[]args)  {  Bb;  Aa=(A)b;  }  }  问题不用多言,as可以解决这个问题。    3,看一个示例:   classA  {   }  classC  {  publicstaticimplicitoperatorA(Ct)  {  returnnewA();  }  }  classB:A  {   }  classProgram  {  staticvoidMain(string[]args)  {  Aa=newB();  Bb=(B)a;  Cc=newC();  a=(A)c;  }  }  对于Bb=(B)a;的IL代码如下:   IL_0008:castclassConsoleApplication1.B   对于a=(A)c;的IL代码如下:   IL_0015:callclassConsoleApplication1.AConsoleApplication1.C::op_Implicit(classConsoleApplication1.C)  区别大家已经看到了,要说真正认识区别那么我们要继续谈“4、用户自定义转换只作用于对象的编译时类型。"   4,看一个示例:   classA  {   }  classC  {  publicstaticimplicitoperatorA(Ct)  {  returnnewA();  }  }  classB:A  {   }  classProgram  {  staticvoidMain(string[]args)  {  Aa=newB();  Bb=(B)a;  objectc=newC();  a=(A)c;//编译通过,运行失败!  }  }

也许你从来没想过a=(A)c;编译会成功,运行会出错在这句,毕竟我们有一个显示类型C到类型A的转换操作,我们看看IL代码即可找到答案,

.methodprivatehidebysigstaticvoidMain(string[]args)cilmanaged  {  .entrypoint  //Codesize28(0x1c)  .maxstack1  .localsinit([0]classConsoleApplication1.Aa,  [1]classConsoleApplication1.Bb,  [2]objectc)  IL_0000:nop  IL_0001:newobjinstancevoidConsoleApplication1.B::.ctor()  IL_0006:stloc.0  IL_0007:ldloc.0  IL_0008:castclassConsoleApplication1.B  IL_000d:stloc.1  IL_000e:newobjinstancevoidConsoleApplication1.C::.ctor()  IL_0013:stloc.2  IL_0014:ldloc.2  IL_0015:castclassConsoleApplication1.A  IL_001a:stloc.0  IL_001b:ret  }//endofmethodProgram::Main

大家注意看IL_0015:castclassConsoleApplication1.A这句,这句说明自定义转换在编译时刻进行,也许你要问为什么不是第3条的:

IL_0015:callclassConsoleApplication1.AConsoleApplication1.C::op_Implicit(classConsoleApplication1.C)

因为objectc,c被定义为Object类型,那么强制转换在编译时刻去Object找是否存在自定义转换操作(注意,()转型时编译器优先考虑自定义转换,找不到才进行castclass),当然Object没有自定义转换为A的操作,那么就使用普通的强制转换castclass。好了现在我们知道了用户自定义转换只作用于对象的编译时类型,而普通的Bb=(B)a;强制转换可以作用到运行时刻。那么上面的错误如何去掉呢?对应代码修改为:

objectc=newC();  Ccc=casC;  a=(A)cc;

现在运行正常通过,好了我们再次查看IL代码

IL_001c:callclassConsoleApplication1.AConsoleApplication1.C::op_Implicit(classConsoleApplication1.C)

到这大家对3和4点的认识应该很清楚了吧。

5、as操作符不能应用于值类型————省略!,鉴于这个点很简单,本人就不提供示例了,大家有兴趣可以自己试验下。

6、看代码示例:(以下代码摘自《EffectiveC#中文版改善C#程序的50中方法》——23页)

publicvoidUseCollection(IEnumerabletheCollection)  {  foreach(MyTypetintheCollection)  t.DoStuff();  }   //上面代码等同于:   publicvoidUseCollection(IEnumerabletheCollection)  {  IEnumeratorit=hteCollection.GetEnumerator();  while(it.MoveNext())  {  MyTypet=(MyType)it.Current;  t.DoStuff();  }  }

通过查看IL代码我们可以确认foreach语句的转换是使用的强制转换操作,那么为什么呢?之所以使用强制转型,是因为foreach语句需要同时支持值类型和引用类型,这侧面说明我们的第5点as不支持值类型。

感谢各位的阅读!关于“C#类型转化需要注意什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI