有关 C# 中对象引用类型转换的问题吗?
我有一个关于对象类型转换的问题。 假设我们有:
A a = new A();
Object o = a;
据我所知,后面发生的事情是编译器会复制a的地址并存储在o变量的内存区域中。那么,我们可以说 a 和 o 引用同一个对象。
如果我们这样做:
String s = "abc";
int a = (int)s;
那么我明白编译器无法将字符串值复制到 int 内存区域。
但如果我们有:
A a = new A();
B b = (B)a;
这在编译时可能没问题。但是,可能会发生运行时错误,例如“无法投射......”。
所以,我不明白内存中实际发生了什么导致上述转换无法执行。难道只是将a的地址复制到b的内存区域吗?如果是这样,为什么不可能呢? 或者它会复制A的所有成员来替换B的所有成员?
谢谢
I have a question regarding Object type casting.
Suppose we have:
A a = new A();
Object o = a;
As I know, what happens behind is that the compiler will copy the address of a and store in the memory area of o variable. Then,we can say that a and o are referencing to the same object.
If we do something like this:
String s = "abc";
int a = (int)s;
Then I understand that the compiler cannot copy the string value to the int memory area.
But if we have:
A a = new A();
B b = (B)a;
This might be ok at the compile time. However, a run time error may happen which is something like "cannot casting....".
So, I dont understand what actually happen in memory that makes the above casting cannot be performed. Is it just copying the address of a to the memory area of b? If so, why it is not possible?
Or it will copy all the members of A to replace all the members of B?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编译器执行静态类型检查,这意味着如果 A 和 B 不属于同一继承层次结构,则不会允许两者之间发生强制转换。
想想看,如果它们不属于同一层次结构,即使编译器允许您将 A 的对象强制转换为 B 的类型,因为 A 不继承自 B 或其继承者,您可能需要调用其中一个方法类型 B 在被转换的对象上,它将在运行时严重失败。
这里有一个有趣的点,如果 B 是一个接口,即使它们不属于同一继承树,编译器也会让强制转换发生:
原因是因为 A 可能来自不同的层次结构树,但A 或其基类之一仍然有可能实现了 B,因此您可能通过该转换得到了一个观点,并且编译器会允许这样做。
The compiler does Static Type Checking meaning that if A and B do not belong to the same inheritance hierarchy, it would not allow a cast to happen between the two.
Think about it, if they are not belong to the same hierarchy, even if compiler lets you cast an object of A to a type of B, since A does not inherit from B or its inheritors, you might want to invoke one of the methods of type B on the casted object and it will fail miserably at runtime.
There is an interesting point exist here though, if B is an interface, the compiler would let the cast to happen even if they do not belong to the same inheritance tree:
The reason for that is because A might be from a different hierarchy tree but there is still possible that A or one of its Base classes have implemented B so you might have a point by that cast and compiler would let that.
正如 Morteza 所解释的,C# 编译器将执行静态类型检查以确定强制转换是否可能。
至于运行时发生的情况,您可能需要查看生成的 IL 以获得更好的了解。对于引用类型,您的转换可能会成为 IL
castclass
指令。这会导致运行时检查实际对象类型以查看强制转换是否有效。如果是,则引用(指向对象的 32 位或 64 位指针)将按照您的预期复制到变量赋值中。如果不是,则抛出 InvalidCastException。对于引用类型对象,单个成员永远不会被复制。仅复制 32/64 位引用。对于值类型对象,各个成员(字段)在赋值期间被复制。
As Morteza explained, the C# compiler will do static type checking to determine if the cast is even possible.
As to what happens at runtime, you may want to take a look at the IL generated to get a better idea. For reference types, your cast will probably become the IL
castclass
instruction. This results in the runtime checking the actual object type to see if the cast is valid. If yes, the reference (a 32-bit or 64-bit pointer to your object) is imply copied in the variable assignment as you expected. If no, an InvalidCastException is thrown.For reference type objects, the individual members are never copied. Only the 32/64-bit reference is copied. For value type objects, the individual members (fields) are copied during assignment.