2009-08-06 31 views
3

我只是在尋找一個例子,而在它我看到的代碼的IntPtr投與新

return new IntPtr(handle); 

各地的我們的代碼戳後,我發現,我們已經使用了類似的模式,但在我們的代碼我們有幾乎相同的東西:

return (IntPtr)handle; 

這兩個需要有區別嗎?第二個會以任何方式「更好」,因爲它沒有分配新的內存,或者只是在下面隱藏了相同的構造函數?

回答

8

在你的例子中,我猜句柄是一個整數值? IntPtr的聲明從的Int32(int)和Int64的(長)顯式轉換簡單地調用相同的構造函數:

public static explicit operator IntPtr(int value) 
{ 
    return new IntPtr(value); 
} 

所以有有力的可讀性可以關注其他的沒有什麼區別。

2

由於IntPtr是一個值類型,使用new不分配任何內存。

從技術上講,調用仍然編譯爲不同的IL - 一個實際調用構造函數,另一個調用顯式轉換運算符。然而,我不確定這兩者之間在JIT通過後是否有任何實際差異 - 很可能沒有(儘管我懷疑您在實踐中會注意到這兩種方式,這是femtooptimization)。

在任何情況下,演員比使用構造函數更習慣用法,所以我建議單獨使用它。

+0

IntPtr是一個值類型的事實並不意味着new不會分配內存。事實上,使用new應該是首選的,以確保結構被正確初始化。 – 2009-08-06 05:40:37

+0

我想帕維爾的意思是,它不使用任何其他方式都不會使用的內存。顯然,複製值類型意味着將使用更多的內存:) – Thorarin 2009-08-06 06:16:00

+0

使用(或不使用)'new'將確保結構已正確初始化絕對沒有任何好處。對於初學者來說,首先你不能有一個「不正確的初始化結構」,因爲編譯器會強制執行本地初始化,並且默認初始化其他所有內容。 – 2009-08-06 07:31:14

5

Reflector說,中投反正調用引擎蓋下的構造:

[Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)] 
public struct IntPtr : ISerializable 
{ 
    ... 

    [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] 
    public static explicit operator IntPtr(int value) 
    { 
     return new IntPtr(value); 
    } 

} 
2

所以這個帖子是空談,沒有號碼,以便讓我們來談談指標。我運行了一些測試代碼,以獲得一些性能指標使用Visual Studio 2010和

我得到這些指標,通過計算10個測試運行的任一方法的平均時間,每次1000萬次迭代,然後在調試然後釋放模式下(非優化然後優化):

(調試) 鑄造方法:〜32毫秒 分配方法:〜26毫秒

(釋放) 鑄造方法:〜20毫秒 分配方法:〜22毫秒

什麼是另外一個有趣的地方是將這些指標與託管C++的類似代碼進行比較,僅使用gcnew,結果大不相同。

再次設置相同。除了比較鑄造方法:「IntPtr^ptr =(IntPtr)i;」 vs分配方法:「IntPtr^ptr =(IntPtr)i;」。

(調試) 鑄造方法:〜91ms 分配方法:〜127ms

(釋放) 鑄造方法:〜22ms內 分配方法:〜124ms

現在,如果你抓你的頭說:那麼爲什麼C#比託管C++快得多,答案不是。使用IntPtr的最有效方式是作爲值類型而不是對值類型的引用。例如像這樣「IntPtr ptr =(IntPtr)i;」。這會給你〜24ms(更多調試)或(〜22發佈模式)。看看它如何被編譯器優化以獲得22ms而不是90ms。

在C#中的結論,除非你真的看到嚴格的緊密代碼,這並不重要。我認爲在Release中我的代碼實際上是優化了演員,因爲評論演員給出了相同的〜22ms。但是大多數情況下,編譯器在C#中都支持這個,至少VS 2010是這樣的。但是,如果您正在查看具有最小性能限制的代碼,請在Managed C++/CLI中注意。編譯器不會自動優化gcnew分配到cast方法,它的速度幾乎快6倍......我在C++/CLI中遇到了這個特殊問題,這導致我在處理某些實時音頻時在此線程上發佈處理。我的代碼(C#):(我管理的C++代碼非常相似,除了必須自己編寫Average()並使用控制檯輸出而不是消息框)。

static void Main() 
    { 
     List<int> castTimings = new List<int>(); 
     List<int> allocTimings = new List<int>(); 

     for (int i = 0; i < TEST_RUNS; ++i) 
     { 
      castTimings.Add(RunCastMethod().Milliseconds); 
      allocTimings.Add(RunAllocationMethod().Milliseconds); 
     } 

     MessageBox.Show(string.Format("Casting Method took: {0}ms", castTimings.Average())); 
     MessageBox.Show(string.Format("Allocation Method took: {0}ms", allocTimings.Average())); 
    } 

    private static TimeSpan RunAllocationMethod() { 
     DateTime start = DateTime.Now; 

     for (int i = 0; i < TEST_ITERATIONS; ++i) 
     { 
      IntPtr ptr = new IntPtr(i); 
     } 

     return (DateTime.Now - start); 
    } 

    private static TimeSpan RunCastMethod() 
    { 
     DateTime start = DateTime.Now; 

     for (int i = 0; i < TEST_ITERATIONS; ++i) 
     { 
      IntPtr ptr = (IntPtr) i; 
     } 

     return (DateTime.Now - start); 
    } 
+0

謝謝你的努力mede – 2010-12-14 05:51:53