我使用反射來創建一些對象。我設置的值是從文件讀入的,所以它們本身就是一種字符串格式,我需要將它們轉換爲屬性的數據類型。哪個更好用:Convert.ToX或X.Parse(...)?
我的問題是,這是更快/更好使用:Convert.ToX(...)
方法或X.Parse(...)
方法?
我使用反射來創建一些對象。我設置的值是從文件讀入的,所以它們本身就是一種字符串格式,我需要將它們轉換爲屬性的數據類型。哪個更好用:Convert.ToX或X.Parse(...)?
我的問題是,這是更快/更好使用:Convert.ToX(...)
方法或X.Parse(...)
方法?
接受類型爲string
的參數的所有Convert.ToX
函數最終都會調用相應數據類型的Parse
方法。
例如,Convert.ToInt32(string)
看起來是這樣的:
public static int ToInt32(string value)
{
if (value == null)
{
return 0;
}
return int.Parse(value, CultureInfo.CurrentCulture);
}
所有的其他數字轉換方法,包括Decimal
和DateTime
同樣的事情。所以你使用哪一個是無關緊要的;無論哪種情況,結果(和速度)都是相同的。
真的,唯一的區別就是開頭的if (value == null)
保護條款。是否方便取決於具體的用例。一般來說,如果您知道您有一個非空string
對象,那麼最好使用Parse
。如果你不確定,ConvertToX
是一個更安全的賭注,需要更少的內聯空值檢查代碼。
好偵探@Cody!我會選擇使用Convert方法,因爲我不必擔心檢查null。 – Micah 2011-05-12 14:32:50
當我不期望它通常是一個錯誤時,變量爲空。所以我想得到一個異常而不是無聲的數據損壞。所以我會說你在使用Convert時比使用parse時更關心空值檢查。 – CodesInChaos 2011-05-12 14:34:46
@代碼:是的,我同意。但有些情況下你沒有*特別的期望。變量既可以爲空也可以爲空是完全合理的。在那種情況下,'Convert'沒有問題。 – 2011-05-12 14:36:01
他們完全一樣! Convert.ToX(String)
方法實際上調用X.Parse(String)
方法。
根據我在Reflector中看到的,Convert表單字符串是Parse的一個包裝。所以它有理由使用解析在性能上稍微好一些。編輯:科迪指出,優化將使差異幾乎沒有什麼,我在我的機器上測試,並確實執行時間爲Parse
和Convert
出來時一樣循環解析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();
}
第一部分或多或少是正確的。但爲什麼你的結論「站得住腳」?這表明他們是同一件事,而不是一個「更好」,甚至稍微如此。 – 2011-05-12 14:34:36
@Cody Gray你是對的我在這裏不清楚,更新了答案 – Menahem 2011-05-12 14:36:42
這也不是真的正確。我認爲這就是你要去的地方,但是一旦JIT編譯器完成了代碼的處理,這兩種方法之間的性能差異幾乎不可能發生。 – 2011-05-12 14:37:37
使用下面的代碼
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。然而,這可能會在你的情況下有所不同,我想你應該做一個類似的測試。
Erm,你沒有認真地嘗試在優化禁用**的情況下以「調試」模式**編譯時測試某些東西的性能,是嗎?這是一個完全沒有意義的**測試。好東西我今天沒有投票了,這很容易-1。 – 2011-05-12 14:44:20
@Cody:只是因爲我爲這個快速示例使用了調試輸出?就這樣你明白了:我在我的一個程序中做了這個快速測試,它被設置爲'Release'並且我使用log4net DEBUG輸出,即使在我的版本中 – yas4891 2011-05-12 14:53:21
是的。我評論中的大膽部分很重要。調試模式禁用所有代碼優化,包括但不限於JIT編譯器。其結果是無意義的數據符合你的直覺,但是一旦應用優化就不會阻礙。使用調試代碼進行性能測試顯示了對每個目的的基本誤解。 – 2011-05-12 14:55:11
另一種可能性是TryParse
方法。如果有可能無法成功解析該值,這些特別有用。呼叫將返回bool
,而不是拋出異常,表示操作是否成功。與處理異常相比,執行速度要快得多,並且是更清晰的實現。
我不能告訴你,但我可以告訴你如何找出...打開ILDasm並打開所有類的DLL(需要一點發現),然後你可以看到他們的IL代碼他們使用。這不是很可讀,但你可以看到它的調用,並檢查是否打電話哪些。 – Matt 2011-05-12 14:24:06
或者只是使用ILSpy來查看C#代碼而不是IL指令... – 2011-05-12 14:25:41
可能的[轉換和解析之間的區別]的重複。(http://stackoverflow.com/questions/3486810/the-difference-between-convert-並解析) – 2011-05-12 15:28:40