2012-02-20 70 views
10

我很想知道是否所有在C#中的轉換都會導致拳擊,如果不是,都會投出昂貴的操作?從Boxing and Unboxing (C# Programming Guide)做所有的C#轉換導致拳擊/拆箱

int i = 123; 
    // The following line boxes i. 
    object o = i; 

採取

示例此線明顯導致拳擊(包起來int類型爲對象)。 這是一個成本很高的操作,因爲它會創建將被收集的垃圾。

那麼來自2種不同類型的參考類型的演員怎麼樣?那是什麼成本?它能被正確測量嗎? (與前面的例子)

例如:

public class A 
{ 
} 

public class B : A 
{ 
} 

var obj = new B(); 
var obj2 = (A)obj; // is this an "expensive" operation? this is not boxing 
+8

從一種引用類型轉換爲另一種引用類型時,沒有涉及拳擊。 – BrokenGlass 2012-02-20 18:17:35

+0

它可以適當測量嗎?應該避免嗎? – 2012-02-20 18:18:16

+0

在將一個引用類型投射到另一個引用時,不涉及裝箱,可能會進行轉換。將一個引用類型轉換爲另一個不相關的引用類型可能會很昂貴。 – 2012-02-20 18:21:49

回答

22

我很想知道,如果在C#中產生的所有轉換在拳擊比賽中。

號只有裝箱轉換導致拳擊,故名‘裝箱轉換’。裝箱轉換都內置在從值類型到引用類型的轉換中 - 無論是值類型繼承的類還是其實現的接口(或通過協變或逆變參考轉換,與其實現的接口兼容的接口)。

都轉換昂貴的操作?

編號標識轉換是零成本,因爲編譯器可以完全消除它們。

隱式和顯式引用轉換的成本是多少?

隱式參考轉換爲零成本。編譯器可以完全消除它們。也就是說,從長頸鹿轉換爲其基本類型動物,或長頸鹿轉換爲其實施的接口類型IAmATallMammal,是免費的。

明確的引用轉換涉及一個運行時檢查,以驗證引用實際上是否引用了所需類型的對象。

運行時檢查是否「昂貴」取決於您的預算。

這個成本是否可以正確測量?

當然。決定什麼資源與你有關 - 比如說 - 然後用秒錶仔細測量你的時間消耗。

你也沒問,但可能是一個問題,應該有:

什麼是最昂貴的轉換?

用戶定義的轉換隻不過是方法調用的語法糖;像任何方法一樣,該方法可以任意長。

動態轉換在運行時再次啓動編譯器;編譯器可能需要很長時間才能執行類型分析,具體取決於您選擇分析問題的難度。

+1

Eric,那麼程序員明確地進行隱式轉換呢?我認爲這也被編譯器忽略了。 (例如:var o =(object)「Some string」; return o.GetHashCode();') – phoog 2012-02-21 14:53:03

+2

@phoog:正確。沒有必要爲此生成IL;字符串引用已經與變量賦值兼容。 – 2012-02-21 15:29:35

10

拳擊意味着把一個值轉換成一個新的參考類型實例。

參考類型之間的標準轉換不會導致任何分配。
(用戶定義類型轉換可以做任何事情)

+0

「從一個引用類型轉換不會導致任何分配。」不一定是真的。 – jason 2012-02-20 18:22:50

+0

@Jason:澄清 – SLaks 2012-02-20 18:25:37

+0

Downvote刪除。 – jason 2012-02-20 18:26:17

7

我很好奇,想知道是否所有在拳擊C#結果轉換,

號拳擊是一項very special operation這意味着治療的一個實例值類型作爲引用類型的一個實例。對於引用類型轉換爲引用類型轉換,該概念不起作用。

都鑄造成本高昂的操作?

簡短的回答:第

龍答:定義昂貴。儘管如此,仍然沒有。

那麼來自2種不同類型的參考類型呢?那是什麼成本?

那麼,如果它只是一個派生的基礎參考轉換?這很快,因爲沒有任何反應。

其他用戶定義的轉換可能會「很慢」,它們可能會「很快」。

這是一個「慢」。

class A { public int Foo { get; set; } } 
class B { 
    public int Foo { get; set; } 
    static Random rg = new Random(); 
    static explicit operator A(B b) { 
     Thread.Sleep(rg.Next()); 
     return new A { Foo = b.Foo; } 
    } 
} 

這是一個「快」。

class A { public int Foo { get; set; } } 
class B { 
    public int Foo { get; set; } 
    static Random rg = new Random(); 
    static explicit operator A(B b) { 
     return new A { Foo = b.Foo; } 
    } 
} 

var obj2 = (A)obj; //這是一個 「昂貴」 的操作?這不是拳擊

不,這是「便宜。「

+0

代價高昂的操作方式==如果我有一個涉及循環+投射(不裝箱)的算法,是不是更加明智地設計它,或者這是一個平凡的操作,不被認爲是性能成本高昂的(就執行時間而言) – 2012-02-20 18:20:05

+0

@liortal:這取決於。如果您關心性能,請對其進行測量。 – SLaks 2012-02-20 18:26:11

+0

我有興趣瞭解它如何工作,而不是專注於性能問題 – 2012-02-20 18:29:38