有趣的重写GetType()方法
来源:互联网 发布:网络犯罪数据研究报告 编辑:程序博客网 时间:2024/06/06 13:59
最近和同事们聚在一起的时候聊起了.net面试题。有一个面试题是问GetType()能否被重载。答案是否定的。原因是GetType()不是Virtual的,所以是不能重载的。不让重载GetType()就是为了保证类型安全。我的一个同事突发奇想,说能否用new来重写GetType()方法。如下面的代码:
运行此程序,它输出:
hello String
啊!难道我们可以随便改一个类的类型?仔细想一想,这只是一个障眼法。让我们来验证一下吧。稍微把代码改一改,去掉这几行前的注释:
Object obj = emp;
Console.WriteLine("obj is System.String = {0}", obj is System.String);
Console.WriteLine("obj is test.Employee = {0}", obj is test.Employee);
再运行, 输出就是:
hello String
obj is System.String = false
obj is test.Employee = true
这说明了什么?说明了emp的类型在CLR看来它还是Employee类型,并不会被你新写的GetType()方法改变。这是为什么呢?我们来看看Main函数的IL代码:
注意L_000f这一行: 编译器生成的IL代码是callvirt指令。callvirt指令能正确地发现基类函数的虚方法和子类的重载方法,并正确地调用合适的方法。在这里被调用的函数是Employee类的GetType()方法。所以后来输出hello String。
另外请注意L_0025这行: isinst string 这是判断栈中当前对象是否string类型。
还有L_003e: isinst test.Employee,这是判断栈中当前对象是否test.Employee类型。
这两条指令之前都是这个指令ldloc.1,指的都是将局部变量obj放入栈,所以obj就是isinst的栈中当前对象。
那为什么我们自己写的新GetType()方法没有将对象原来的GetType()方法覆盖掉呢?
这是因为每个方法都有自己的方法签名。对象原来的GetType()方法在metadata中的method 表中,而且有一个与众不同的方法签名。我们自己写的新GetType()方法也是在metadata中的method 表中,也有一个方法签名,这个方法签名唯一标识每一个方法。CLR在查看一个对象的类型时,是固定用对象原来的GetType()方法签名去找GetType()方法,这样就不会调用错误的方法。我们自己写的新GetType()方法在检查类型的时候是不会被调用的。我们自己写的新GetType()方法只有在callvirt指令中才能调用到。
- 有趣的重写GetType()方法
- 是否需要覆盖ContentProvider的getType方法?
- 是否需要覆盖ContentProvider的getType方法?
- 是否需要覆盖ContentProvider的getType方法?
- ContentProvider中getType方法的作用
- ContentProvider 中getType()方法的认识
- Object.GetType 方法
- PHP方法之gettype
- Android中关于ContentProvider类的getType()方法的理解
- c# 反射时GetType方法查找Type的分析
- 对ContentProvider中getType方法的一点理解
- 一个有趣的方法
- ContentProvider的getType
- c# System.Type.GetType()方法
- gettype
- 方法的重写
- JAVA-方法的重写
- 方法重写的规则
- 环境变量生效
- 关于在C#下实现人民币大小写转换问题
- spring与xwork整合
- 环境变量生效
- 路径名查找
- 有趣的重写GetType()方法
- 在重构的过程中,什么情况下应该使用设计模式?应该用哪种模式?
- 精进不休 .NET 4.0 (8) - ADO.NET Entity Framework 4.0 Self Tracking Entity
- JSF页面上的文本编辑器的问题
- 路径名查找(续)
- 如何在地址栏显示网站图标
- Noun Clauses
- 今天在工大的机器人大赛
- java myecplise7.0 生成注册码代码