前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《CLR via C#》Part2之Chapter4 类型基础(二)

《CLR via C#》Part2之Chapter4 类型基础(二)

作者头像
Isaac Zhang
发布2019-09-11 16:55:25
3930
发布2019-09-11 16:55:25
举报
文章被收录于专栏:奔跑的人生

类型转换

CLR最重要的特性之一是安全性,在运行时,通过调用GetType(),总是知道一个对象的确切类型。

CLR允许将一个对象转换为它的实际类型或者它的任何基类型。Eg: C#可直接将一个对象转换为它的任何基类,因为向基类转换被认为是一种安全的隐式转换。但是将对象向它的某个派生类转换时,C#要求必须显示转换,因为这种转换可能在运行时报错。

类型伪装是去多安全漏洞的根源

在C#中还有is和as两种转换方式:

  1. is转换:is检查一个类型是否兼容于指定的类型,并返回一个Boolean值。(is操作符永远不会抛出异常,只会返回ture or false) 1: Object o = new Object; 2: Boolean b1 = (o is Object);//return ture 3: Boolean b2 =(o is IsaacType);//return false
  2. as转换:C#专门提供as操作符,目的是为了简化转换形式,并提高性能。

1: //is的使用形式 2: if(o is IsaacZhang) 3: { 4: IsaacZhang isaac = (IsaacZhang)o; 5: //开始使用isaac 6: } 7: //as的使用形式 8: IsaacZhang isaac = o as IsaacZhang; 9: if(isaac!=null){ 10: //使用isaac 11: }

<!-- .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } --><!-- .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } -->

在使用as的形式,如果o不兼容IsaacZhang类型,将返回一个Null;因为使用as操作符,CLR只会校验一次对象的类型,所以性能有所提升。

命名空间和程序集

在C#中我们使用using引入命名空间,但是CLR并不知道命名空间的任何事,访问一个类型时,CLR需要知道类型的完整名称(长的、包括句点符号的名称)以及该类型的定义具体在哪个程序集中。

默认情况下,C#编译器会自动在MSCorLib.dll程序集中查找“引用的类型”,即使你没有显式的告诉它。MSCorLib.dll包含了所有核心Framework类库(FLC)类型的定义,比如Object、Int32、String等。

有时候,为了消除歧义,必须显示的告诉编译器要创建的是哪一个类型

代码语言:javascript
复制
   1:  //Isaac.Test中包含一个IsaacZhang类型
代码语言:javascript
复制
   2:  //Isa.Common中也包含一个IsaacZhang类型
代码语言:javascript
复制
   3:  using Isaac.Test;
代码语言:javascript
复制
   4:  using Isa.Common;
代码语言:javascript
复制
   5:   
代码语言:javascript
复制
   6:  public sealed class Program{
代码语言:javascript
复制
   7:          public static void Main(){
代码语言:javascript
复制
   8:                   Isaac.Test.IsaacZhang isaac = new Isaac.Test.IsaacZhang;//无歧义
代码语言:javascript
复制
   9:          }
代码语言:javascript
复制
  10:  }

C#的using还支持使用别名的形式引用命名空间。如:using alias = Isaac.Test;

C#还提供了一个名为“外部别名(extern alias)”(外部别名甚至还允许从同一个程序集中的不同版本访问一个类型)

命名空间和程序集的关系
命名空间和程序集的关系

运行时的相互联系

这一节解释类型、对象、线程栈、和托管堆在运行时的相互关系。此外,还将调用静态方法、实例方法和虚方法的区别。

下图展示了CLR的一个Microsoft Windows进程。

Microsoft Windows进程
Microsoft Windows进程

在这个进程中,可能存在多个线程。一个线程创建时,会分配到一个1M大小的栈,这个栈的空间用于向方法传递参数。

M1方法开始执行时,在线程栈上分配局部变量name的内存,如下图:

2013-3-9 22-35-53
2013-3-9 22-35-53

然后M1调用M2方法,将局部变量作为一个实参来传递,这造成name变量的地址被压入栈,如下图:

2013-3-9 22-40-58
2013-3-9 22-40-58

M2方法内部的代码开始执行前,为length和tally分配内存,然后执行代码,当M2执行到return语句,造成CPU的指令指针被设置成栈中的返回地址。如下图:

2013-3-9 22-47-04
2013-3-9 22-47-04

最终,M1会返回到它的调用者。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-03-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类型转换
    • 在C#中还有is和as两种转换方式:
    • 命名空间和程序集
    • 运行时的相互联系
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档