簡體   English   中英

有關C#中對象引用類型轉換的問題?

[英]Questions regarding object reference type casting in 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的所有成員?

謝謝

編譯器執行靜態類型檢查意味着如果A和B不屬於同一繼承層次結構,則不允許在兩者之間發生強制轉換。

考慮一下,如果它們不屬於同一層次結構,即使編譯器允許您將A的對象轉換為B類型,因為A不從B或其繼承者繼承,您可能想要調用其中一個方法在鑄造對象上的類型B,它將在運行時失敗。

class A { }
class B { 
    void Foo() { }
}

A a = new A();
B b = (B)a;      // Compiler Error

// Hypothetically, if above was allowed, the below would ALWAYS fail at runtime
// Since there is no way the object "b" can handle this call.
b.Foo();


這里有一個有趣的觀點,如果B是一個接口,編譯器會讓強制轉換發生,即使它們不屬於同一個繼承樹:

class A { }
interface B { 
    void Foo();
}

A a = new A();
B b = (B)a;      // Compiler lets this happens 

// Even though A does not implement B, but still one of the base classes of A 
// might have implement B and A inherits that so it might be able to handle this
b.Foo();

原因是因為A可能來自不同的層次結構樹,但仍有可能A或其中一個基類實現了B,因此您可能有一個點,而編譯器會允許它。

正如Morteza所解釋的那樣,C#編譯器將執行靜態類型檢查以確定是否可以進行轉換。

至於在運行時發生的事情,您可能需要查看生成的IL以獲得更好的想法。 對於引用類型,您的castclass可能會成為IL castclass指令。 這會導致運行時檢查實際的對象類型以查看強制轉換是否有效。 如果是,則將引用(指向對象的32位或64位指針)隱含在變量賦值中,如預期的那樣。 如果不是,則拋出InvalidCastException。

對於引用類型對象,永遠不會復制各個成員。 僅復制32/64位引用。 對於值類型的對象,單獨的成員(字段) 分配期間被復制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM