![]() |
1
1
所有这些类型转换都是多余的,我确信编译器会对它们进行优化。
这就是我的意思。
编辑 结果,我完全错了。 This 文档描述了发生的情况:
|
![]() |
2
4
将C类改为:
杰弗里·里克特的解释: C编译器要求实现接口的方法标记为public。这个 clr要求将接口方法标记为virtual。如果你没有明确的标记 方法在源代码中是虚拟的,编译器将该方法标记为虚拟的和 密封;这将防止派生类重写接口方法。如果你明确 将该方法标记为虚方法,编译器将该方法标记为虚方法(并保留它 未密封);这允许派生类重写接口方法。 如果接口方法是密封的,则派生类不能重写该方法。然而,A 派生类可以重新继承同一个接口,并且可以为 接口的方法。当对对象调用接口的方法时,实现 调用与对象类型关联的。 因为C类也实现了I接口,比我们在C对象上调用接口方法时,我们将调用与对象类型对应的实现被调用(即C类方法),而不是从C的基类(而不是类方法)派生的方法。 |
![]() |
3
1
我认为您误解了Cast运算符对引用转换的作用。 假设您引用了堆栈上的C实例。这是一组特定的位。你把堆栈上的东西投射到A上。位会改变吗?不,没什么变化。它是对同一对象的相同引用。现在你把它投给我。这次比特会改变吗?不。 相同的位。相同的参考。相同的对象。 通过类似这样的强制转换进行的隐式引用转换 编译程序 使用不同的规则 在编译时找出要调用的方法 . 所以对“a”的强制转换是完全不相关的,被编译器忽略了。编译器知道或关心的只是您有一个I类型的表达式,并且您正在对它调用一个方法。编译器生成一个调用,该调用表示“在运行时,查看堆栈上的对象引用,并调用对象“i.m1”槽中的任何对象。 解决这个问题的方法是考虑插槽。每个接口和类都定义了一定数量的“插槽”。在运行时,类的每个实例都有这些槽,其中填充了对方法的引用。编译器生成的代码说“调用该对象的槽3中的任何内容”,这就是运行时所做的——在槽中查找,调用那里的内容。 在您的示例中,有各种各样的槽。接口需要三个槽,基类提供更多,派生类的“新”方法提供更多。构造派生类的一个实例时,将填充所有这些槽,并且可以理解,与i关联的槽中填充了派生类的匹配成员。 这有道理吗? |
![]() |
4
0
铸造并不重要,因为C已经包含A和I。
对于((i)((a)c)).m1()和((i)((a)c)).m3():
对于((i)((a)c)).m2():
|
![]() |
Jiji · 将简单对象强制转换为简单的通用接口 7 年前 |
![]() |
tobeypeters · 反射铸造 7 年前 |
![]() |
Alex · 是否改为存储字符串的整数的通用ArrayList? 7 年前 |
![]() |
Kai · 如何在C#中转换会话中存储的词典? 7 年前 |
![]() |
Ján ЯabÄan · 布尔值到双精度的快速转换方法 7 年前 |