2014-03-25 133 views
2

爲什麼類型轉換昂貴?類型轉換需要什麼?爲什麼類型轉換昂貴?

好的,我知道它的價值類型,但讓我們暫時排除它們。我們來談談引用類型之間的轉換。如果我這樣寫:

class Animal { } 

class Dog : Animal { } 

例1

var dog = new Dog(); 

object obj = dog; 

例2

public Animal GetAnimal() 
{ 
    return new Dog(); 
} 

object obj = GetAnimal(); 

多少類型轉換就上面的例子中包含他們爲什麼貴?

據我所知,它只是一個新的4字節指針,必須分配在線程的本地參數堆棧上,並且新創建的引用指針的對象引用指向同一個舊地址。爲什麼這是一件昂貴的事情?正在分配一個新的對象引用CPU密集型?然後,甚至抄襲同一個對象引用必須在下面的例子中意味着該成本,如:

Animal fish = new Animal(); 

Animal anotherFish = fish; 

那一定是同樣昂貴呢?

+6

請定義「昂貴」......是什麼讓你覺得他們*是昂貴的? –

+1

@JonSkeet:這真是我問題的一部分。泛型或泛型的全部論點是避免了與類型轉換相關的成本。我意識到,我一直在考慮這一點,卻沒有多少考慮。我認爲直到現在,它涉及更多的CPU時間,這是昂貴的。 –

+1

一個說明。使用[轉換運算符](http://msdn.microsoft.com/zh-cn/library/09479473.aspx),「類或結構可以轉換爲和/或從其他類或結構或基本類型轉換。相反,使用[casts](http://msdn.microsoft.com/zh-cn/library/ms173105.aspx):「引用類型之間的轉換操作不會更改基礎對象的運行時類型;它只會更改用作該對象引用的值的類型。有關更多信息,請參閱[多態](http://msdn.microsoft.com/zh-cn/library/ms173152.aspx)。「 –

回答

5

強制轉換爲基本類型在運行時始終爲空。當你寫:

Dog dog = new Dog(); 
object obj = dog; 

的JIT認爲:

void* dog = new Dog(); 
void* obj = dog; 

的JIT並不特別在意在這種情況下,不同的引用類型。對此,所有的ref類型都只是指針。 JIT完全有能力處理瑣碎的冗餘變量和分配。

由於必須進行運行時檢查,因此對派生類的強制轉換通常會產生運行時成本。這有時可以優化。如果檢查是確有必要,它看起來有點像這樣:

object obj = new Dog(); 
AssertCastValid<Dog>(obj); 
Dog dog = obj; //Invalid C#, but OK for the JIT internally 

隨着AssertCastValid是代碼來驗證運行時類型。下面是它可能樣子(雖然它可能不):

bool AssertCastToDogValid(object obj) { return obj.GetType() == typeof(Dog); } 

(這是不正確的,但說明了這個想法。)

正如你所看到的,upcasts都是免費和向下轉型通常不是免費的。多麼昂貴?這與您在代碼中進行的其他操作有關,它取決於具體情況(層次深度,轉換爲接口,...)。

+0

謝謝@usr。那麼變體泛型類型必須承擔相同的成本,對吧? –

+0

@ WaterCoolerv2你對泛型類型所做的一切都是靜態地保證在運行時成功(想想看 - 什麼操作可能會失敗?沒有。)。所有靜態安全的東西都不需要運行時檢查。泛型確實比非泛型代碼有成本,但它不在於強制轉換。 – usr

+1

非常感謝@usr。 –