吐槽一下:這個問題比其看起來要難得多得多啊。
大家的讨論最終還是沒有一個完全正确的答案,不過我根據讨論結果總結了一個差不多算是最終版的代碼,這裡分享出來,畢竟這是大家共同的智慧結晶,沒有交流和碰撞就沒有這段代碼。

其存在的問題主要是 char 和 bool 類型還是會被當做數值,以及判斷順序需要小幅優化。
除了對上述存在問題的改進,還重新調整為3個方法,分别是用來判斷是否為數值類型、可空數值類型及可空類型。
使用這個測試代碼跑可以通過,基本涵蓋了常用類型。
需指出的是:
這裡對可空類型判斷沒有使用 GetType() 方法擷取類型對象,因為我測試了一下,可空類型執行 GetType() 傳回的仍然是不可空的原類型,直接進行判斷是否為數值類型即可。
那麼為什麼還要做針對可空類型的判斷呢?如果你試過在 ASP.Net Mvc 中擷取到模型屬性的 ModelMetadata 你就會知道,其 ModelType 屬性傳回的就是 Nullable<> 類型,可空類型的判斷就是給這種情況使用的。
我們就以上面的測試代碼來跑,注意這是循環五十萬輪的測試,每輪執行該方法36次,共計執行一千八百萬次,我們讓代碼連續跑三遍,取第三遍的時間結果(第一遍的包含初始化流程,肯定會慢一些)。
我們的代碼測試結果:
可以看出這個效率還是蠻高的,平均每輪耗時:0.016546毫秒,平均每次執行方法耗時:0.0004596111111毫秒
然後我們把老外的代碼拿過來看一下,它跑不通這個測試,因為以下類型它沒做判斷:Decimal、Byte、UIntPtr 。
還有個我們測試代碼之外的 IntPtr 。
加上這些類型的判斷之後,主體方法代碼如下:
老外的代碼測試結果:
這是妥妥的輸給我們了,老外給咱跪了,那些支援簡單粗暴實打實的朋友錯了。
但是稍等一下,老外的代碼裡其實有些明顯的重複判斷,比如在C#中 typeof() 擷取的 int 和 Int32 其實是一樣的,我們來優化一下這些重複:
優化版的老外代碼測試結果:
哈,老外還是跪給我們了。
下面我們再将這個代碼改進為使用 TypeCode 方式進行判斷,這會提高一些性能。
但是需要注意:
從 Enum 類型中擷取到的 TypeCode 會是對應 Int32 類型,這不是我們要的結果,需要額外對其進行判斷。
TypeCode 枚舉中是沒有 IntPtr 和 UIntPtr 項的,是以還是要做額外判斷。
改進後的代碼:
老外的代碼改進為用 TypeCode 方式進行判斷後的測試結果:
這個效果就很不錯了,一千八百萬次的量級,僅僅是比我們的最終代碼慢了81毫秒(實測三遍時是穩定地輸給我們的代碼,不是飄出來的偶然浮動結果),這個性能差距可以忽略了。
這也可以看做是另一個最終版的代碼了,因為如果根據你的使用環境來把常用類型放到最前面的話,性能還會更好(盡管你根本感覺不到單次萬分之幾毫秒的差别),但是不可回避的是對那些我們沒有預見到的類型的支援問題,比如這 IntPtr 和 UIntPtr ,在我們前面給出的最終版代碼中這兩個類型是未做特殊适配就天然支援的。
是以如果你重視優雅度、擴充性和編碼知識層級的話,還是建議你使用我前面給出的最終代碼。
看似非常簡單的問題,背後卻有這麼深的水啊,若沒有大家的讨論,斷然不會得到這樣的成果,并且學到這麼多知識。
沒有完美的代碼,我們期待更好,在此繼續讨論吧,也許交流碰撞後還會有更優秀的方案!
本文轉自斯克迪亞部落格園部落格,原文連結:http://www.cnblogs.com/SkyD/p/4058486.html,如需轉載請自行聯系原作者