2011-05-12 58 views
6

我使用反射來創建一些對象。我設置的值是從文件讀入的,所以它們本身就是一種字符串格式,我需要將它們轉換爲屬性的數據類型。哪個更好用:Convert.ToX或X.Parse(...)?

我的問題是,這是更快/更好使用:Convert.ToX(...)方法或X.Parse(...)方法?

+1

我不能告訴你,但我可以告訴你如何找出...打開ILDasm並打開所有類的DLL(需要一點發現),然後你可以看到他們的IL代碼他們使用。這不是很可讀,但你可以看到它的調用,並檢查是否打電話哪些。 – Matt 2011-05-12 14:24:06

+2

或者只是使用ILSpy來查看C#代碼而不是IL指令... – 2011-05-12 14:25:41

+1

可能的[轉換和解析之間的區別]的重複。(http://stackoverflow.com/questions/3486810/the-difference-between-convert-並解析) – 2011-05-12 15:28:40

回答

11

接受類型爲string的參數的所有Convert.ToX函數最終都會調用相應數據類型的Parse方法。

例如,Convert.ToInt32(string)看起來是這樣的:

public static int ToInt32(string value) 
{ 
    if (value == null) 
    { 
     return 0; 
    } 
    return int.Parse(value, CultureInfo.CurrentCulture); 
} 

所有的其他數字轉換方法,包括DecimalDateTime同樣的事情。所以你使用哪一個是無關緊要的;無論哪種情況,結果(和速度)都是相同的。

真的,唯一的區別就是開頭的if (value == null)保護條款。是否方便取決於具體的用例。一般來說,如果您知道您有一個非空string對象,那麼最好使用Parse。如果你不確定,ConvertToX是一個更安全的賭注,需要更少的內聯空值檢查代碼。

+0

好偵探@Cody!我會選擇使用Convert方法,因爲我不必擔心檢查null。 – Micah 2011-05-12 14:32:50

+0

當我不期望它通常是一個錯誤時,變量爲空。所以我想得到一個異常而不是無聲的數據損壞。所以我會說你在使用Convert時比使用parse時更關心空值檢查。 – CodesInChaos 2011-05-12 14:34:46

+0

@代碼:是的,我同意。但有些情況下你沒有*特別的期望。變量既可以爲空也可以爲空是完全合理的。在那種情況下,'Convert'沒有問題。 – 2011-05-12 14:36:01

1

他們完全一樣! Convert.ToX(String)方法實際上調用X.Parse(String)方法。

1

根據我在Reflector中看到的,Convert表單字符串是Parse的一個包裝。所以它有理由使用解析在性能上稍微好一些。編輯:科迪指出,優化將使差異幾乎沒有什麼,我在我的機器上測試,並確實執行時間爲ParseConvert出來時一樣循環解析100萬inetger時。編輯2:在這裏你去yas4891,它實際上是你使用的代碼,只是非常小的變化。

public static void Main() 
     { 
      int tRuns = 1000000; 
      List<String> tList = new List<string>(); 
      for (int i = 0; i < tRuns; i++) tList.Add(i.ToString()); 
      Stopwatch s = new Stopwatch(); 
      s.Start(); 
      int tSum = 0; 
      for (int i = tRuns - 1; i >= 0; i--) 
      { 
       tSum += Convert.ToInt32(tList[i]); 
      } 
      s.Stop(); 
      Console.WriteLine("convert: " + s.ElapsedMilliseconds); 

      Console.WriteLine("tSum:" + tSum); 

      s.Reset(); 
      s.Start(); 
      tSum = 0; 
      for (int i = tRuns - 1; i >= 0; i--) 
      { 
       tSum += Int32.Parse(tList[i]); 
      } 
      s.Stop(); 
      Console.WriteLine("parse: " + s.ElapsedMilliseconds); 
      Console.WriteLine("tSum:" + tSum); 
      Console.ReadKey(); 
     } 
+0

第一部分或多或少是正確的。但爲什麼你的結論「站得住腳」?這表明他們是同一件事,而不是一個「更好」,甚至稍微如此。 – 2011-05-12 14:34:36

+0

@Cody Gray你是對的我在這裏不清楚,更新了答案 – Menahem 2011-05-12 14:36:42

+0

這也不是真的正確。我認爲這就是你要去的地方,但是一旦JIT編譯器完成了代碼的處理,這兩種方法之間的性能差異幾乎不可能發生。 – 2011-05-12 14:37:37

-1

使用下面的代碼

int tRuns = 1000000; 
List<String> tList = new List<string>(); 

for (int i = 0; i < tRuns; i++) 
    tList.Add(i.ToString()); 


PerformanceMeter.Start(); 
int tSum = 0; 
for (int i = tRuns-1; i >= 0; i--) 
{ 
    tSum += Convert.ToInt32(tList[i]); 
} 

PerformanceMeter.LogAndStop("using Convert.ToInt32:"); 

cLogger.Info("tSum:" + tSum); 
PerformanceMeter.Start(); 

tSum = 0; 
for (int i = tRuns-1; i >= 0; i--) 
{ 
    tSum += Int32.Parse(tList[i]); 
} 

PerformanceMeter.LogAndStop("using Int32.Parse:"); 
cLogger.Info("tSum:" + tSum); 

給我下面的輸出:

{} PerformanceMeter:178信息: - 使用Convert.ToInt32 :: 233,0133毫秒
{程序}:92信息: - tSum:1783293664
{PerformanceMeter}:178信息: - 使用Int32.Parse :: 179,0103 ms
【程序】:102信息: - TSUM:1783293664

所以至少的Int32它似乎是更有效地使用Int32.Parse。然而,這可能會在你的情況下有所不同,我想你應該做一個類似的測試。

+0

Erm,你沒有認真地嘗試在優化禁用**的情況下以「調試」模式**編譯時測試某些東西的性能,是嗎?這是一個完全沒有意義的**測試。好東西我今天沒有投票了,這很容易-1。 – 2011-05-12 14:44:20

+0

@Cody:只是因爲我爲這個快速示例使用了調試輸出?就這樣你明白了:我在我的一個程序中做了這個快速測試,它被設置爲'Release'並且我使用log4net DEBUG輸出,即使在我的版本中 – yas4891 2011-05-12 14:53:21

+0

是的。我評論中的大膽部分很重要。調試模式禁用所有代碼優化,包括但不限於JIT編譯器。其結果是無意義的數據符合你的直覺,但是一旦應用優化就不會阻礙。使用調試代碼進行性能測試顯示了對每個目的的基本誤解。 – 2011-05-12 14:55:11

1

另一種可能性是TryParse方法。如果有可能無法成功解析該值,這些特別有用。呼叫將返回bool,而不是拋出異常,表示操作是否成功。與處理異常相比,執行速度要快得多,並且是更清晰的實現。