标签:
CLR 最重要的一个特性就是类型安全。CLR 在运行时总能知道一个对象的类型。我们也可以用过调用 GetType方法来得到对象的准确类型。因为该方法是一个虚方法。所以我们不可能利用它来篡改一个类型的信息。
例如:我们不可能重写 Employee 类的 GetType方法使之返回一个SpaceShuttle类型。
作为开发人员,我们经常会遇到需要将一个对象转换为其他类型。 CLR 允许我们将对象转换为其原来的类型或者它的任何一个基类型。各个编程语言自己决定如何提供这些转型操作。
例如,C# 不需要任何特殊的语法就可以将对象转换为其任何一个基类型,因为转换为基类型被认为是安全的隐式操作。然而在其将对象转换为它的任何派生类型时,C# 要求进行显式转换,因为这样的转型有可能会失败
下面的代码将演示如何将对象转化为它的基类和派生类型:
1 //该类型隐式继承自 System.Object 2 class Employee{ 3 ... 4 } 5 6 class App{ 7 public static void Main(){ 8 9 //这里不需要转型,因为 new 返回的是一个 Employee 对象 10 //而 Object 又是 Employee 的基类型 11 Object o = new Object (); 12 13 //这里需要转型,因为 Employee 继承自 Object 14 //其它一些语言可能不需要转型 15 Employee e = ( Employee )o; 16 17 } 18 }
上面的例子显示了要使代码通过编译我们需要做的一些事情,下面解释运行时发生的行为,在运行时CLR会检查转型操作以确保总是将对象转型它的实际类型、或者它的任何基类型。
例如,下面的代码虽然能够通过编译,但是运行时,却会抛出 InvalidCastException 异常:
1 class Manager:Employee { 2 3 ... 4 5 } 6 7 8 class App{ 9 10 public static void Main() { 11 12 //构造一个 Manager 对象并将其传递给 PromoteEmployee 13 14 //一个 Manager " Is-A" Object.PromoteEmployee 将正常运行 15 16 Manager m = new Manager(); 17 18 PromoteEmployee(m); 19 20 21 //构造一个DateTime 对象并将其传递给 PromoteEmployee 22 23 //由于 DateTime 并非继承自 Employee,因此 PromoteEmployee 会抛出一个 System.InvalidCastException 异常 24 25 DateTime newYears = new DateTime(2016,1,1); 26 27 PromoteEmployee(newYears); 28 29 } 30 31 public static void PromoteEmployee(Object o) { 32 33 //这里,编译器并不知道对象 o 引用的实际类型,所以编译器允许代码通过编译 34 35 //当代码运行时,CLR会获知 o 的引用类型(每当进行转型操作时), 36 37 //并且会检查对象的类型是否是Employee,或者是任何继承自Employee的类型 38 39 Employee e = (Employee) o; 40 41 ... 42 43 } 44 45 }
如果 CLR 允许上例中的转型操作,代码则会失去类型安全,并且结果也将变得不可预期——包括应用程序可能崩溃、以及由于类型欺骗引起的安全漏洞。
类型欺骗是很多安全漏洞的原因,它会极大地危机应用程序的 稳定性和健壮性。
* PromoteEmployee()的正确定义应该是接受一个 Employee对象,而不是 Object 对象作为参数,本文使用 Object 的目的仅仅只是为了演示编译器和 CLR 是如何处理转型操作的。
标签:
原文地址:http://www.cnblogs.com/Vanilla-611/p/5787034.html