对象本身没有被修改,这就是为什么对象的类型仍然在调试器中显示为“ParentClass”的原因。
考虑下面的例子,我认为这是例证性的。你认为在这里输出到控制台是什么?
class Program
{
public class ParentClass
{
public virtual void foo()
{
Console.WriteLine("parent.foo");
}
public virtual void bar()
{
Console.WriteLine("parent.bar");
}
}
public class InheritedClass : ParentClass
{
public new void foo()
{
Console.WriteLine("inherited.foo");
}
public override void bar()
{
Console.WriteLine("inherited.bar");
}
}
static void Main(string[] args)
{
var inherited = new InheritedClass();
var parent = inherited as ParentClass;
var d = parent as dynamic;
parent.foo();
inherited.foo();
d.foo();
parent.bar();
inherited.bar();
d.bar();
Console.Read();
}
}
只有一个对象被创建,然后它会创建两个引用:一个继承的静态类型,和一个与“动态”类型。所有引用引用同一个对象的情况都可以通过调用“bar”调用“InheritedClass.bar”来实现,而不管静态类型如何(运行时类型始终相同)。但是,请注意使用“覆盖”和“新”之间的区别:您将看到“parent.foo()”调用“ParentClass.foo”方法。这是因为“父”变量是静态类型“ParentClass”类型,所以C#编译器发出IL指令来调用“ParentClass”上的方法。您可以进一步看到“动态”类型引用仍然调用“InheritedClass.foo”,因为动态类型在运行时解析,并且这解析为实际运行时类型,即“InheritedClass”。
编辑 @InBetween有一个重要的区别,我没有考虑。在从值类型转换为引用类型(反之亦然)的情况下,新对象为实际创建,因为新内存必须分别在堆或堆栈上分配(“装箱”过程)。当然,部分由于这个原因,struct
和其他值类型不支持虚拟方法。
如果它是一个ChildClass,那么你将在调试器中看到,你只是将它转换成一个'ParentClass'而不是转换它,它仍然是一个'ChildClass'并且可以退回。 – 2014-11-06 17:23:01
因为它实际上是在内存中键入'ChildClass'的引用。演员阵容不会改变这一点。 – 2014-11-06 17:28:31
所以“as”实际上不会以任何方式修改对象?它只是验证给定一个对象的引用,继承结构是兼容的? – Tim 2014-11-06 17:34:21