對象本身沒有被修改,這就是爲什麼對象的類型仍然在調試器中顯示爲「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