Double.TryParseまたはConvert.ToDouble-どちらがより速く、より安全ですか?


80

私のアプリケーションは、VSTOを使用してExcelファイルを読み取り、読み取ったデータをに追加しますStringDictionary。数桁の数字であるデータのみを追加します(1000 1000,2 1000,34-コンマはロシアの標準では区切り文字です)。

現在の文字列が適切な数値であるかどうかを確認する方がよいでしょうか。

object data, string key; // data had read

try
{
  Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
  dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
  // is not a number
}

または

double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
  dic.Add(key, str);
}

次の解析アルゴリズムの問​​題のため、StringDictionary代わりにを使用する必要がありDictionary<string, double>ます。

私の質問:どちらの方法が速いですか?どちらが安全ですか?

そして、それは呼び出す方が良いですConvert.ToDouble(object)Convert.ToDouble(string)


参考までに、double.TryParseはtry {result = double.Parse(s);と同じです。trueを返します。} catch {return false; }。Convertは本質的に、多数のオーバーロードを伴う両方のラッパーです。それはあなたがそれをする方法に違いはありません。しかし、ジョンが指摘したように、悪い入力を処理する方法を考えてください。
John Leidegren 2009

12
Double.TryParseは、try..catchでラップされたdouble.Parseと同じではありません。セマンティクスは同じですが、コードパスが異なります。TryParseは最初に、内部のNumber.TryStringToNumberを使用して文字列が数値であることを確認しますが、Parseはそれがすでに数値/ doubleであると想定します。
ジェフモーザー

回答:


131

リリースモードで簡単な非科学的テストを行いました。両方のメソッドに「2.34523」と「badinput」の2つの入力を使用し、1,000,000回繰り返しました。

有効な入力:

Double.TryParse = 646ms
Convert.ToDouble = 662 ms

予想通り、それほど違いはありません。すべての意図と目的のために、有効な入力のために、これらは同じです。

無効入力:

Double.TryParse = 612ms
Convert.ToDouble = ..

まあ..それは長い間実行されていました。1,000回の反復を使用してすべてを再実行しConvert.ToDoubleましたが、入力が正しくないと8.3秒かかりました。平均すると、2時間以上かかります。テストがどれほど基本的であるかは関係ありません。無効な入力の場合、Convert.ToDouble例外を発生させるとパフォーマンスが低下します。

だから、これはTryParseそれをバックアップするためのいくつかの数字での別の投票です。


4
上記に加えて、Convert.ToDouble()が科学的記数法の数値で例外をスローすることがわかりました。これを考慮してください:double toDouble = Convert.ToDouble((-1/30000).ToString()); //失敗しますdoubledblParse = Double.Parse((-1/30000).ToString()); //正常に動作します
Buddy Lee

46

そもそも、そもそも使うのdouble.Parseではなく使ってみたいと思いますConvert.ToDouble

あなたが使用する必要があるかどうかのParseTryParse:不正な入力データがあります場合は、続行するか、ということが本当に例外的な状態であることができますか?例外的なParse場合は、入力が悪い場合に使用して爆発させます。期待どおりにきれいに処理できる場合は、を使用してくださいTryParse


6
ジョン、Convert.ToDoubleよりもdouble.Parseを好む理由を詳しく説明していただけますか?
デビッドノース

10
@dnorthut:基本的に、nullを0に変換することはめったにありません(Convert.ToDoubleが行います)。また、一般的に柔軟性があります。私はちょうど...特定の方法のために行く傾向がある
ジョンスキート

8

.NET Frameworkの設計ガイドラインでは、Tryメソッドの使用を推奨しています。通常、例外を回避することをお勧めします。

Convert.ToDouble(object) しましょう ((IConvertible) object).ToDouble(null);

どちらが呼び出す Convert.ToDouble(string, null)

したがって、文字列バージョンを呼び出す方が高速です。

ただし、文字列バージョンはこれを実行します。

if (value == null)
{
    return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);

したがって、double.Parse直接行う方が高速です。


7

例外を処理しない場合は、TryParseを使用してください。TryParseは、例外スタックトレース全体を処理する必要がないため、より高速です。


7

私は一般的にConvertクラスを避けようとします(つまり、私はそれを使用しません)。なぜなら、それは非常に紛らわしいと思うからです。Convertしているためです。同じコードで多くの意味的に非常に異なる変換が発生する可能性があるます。 。これにより、プログラマーが何が起こっているのかを正確に制御することが困難になります。

したがって、私のアドバイスは、このクラスを使用しないことです。それも実際には必要ありません(ToString数値クラスの通常のメソッドはこれを行うための適切なメソッドを提供しないため、数値のバイナリ形式を除きます)。


7

入力が100%確実でない限り(まれですが)、Double.TryParseを使用する必要があります。

Convert.ToDouble will throw an exception on non-numbers
Double.Parse will throw an exception on non-numbers or null
Double.TryParse will return false or 0 on any of the above without generating an exception.

例外よりもそれほど遅くないため、例外をスローすると、解析の速度は2次的になります。


4

ここでのConvertクラスには多くの嫌悪感があります...少しバランスを取るために、Convertには1つの利点があります-オブジェクトが渡された場合、

Convert.ToDouble(o);

oがすでにDouble(またはintまたは簡単にキャストできるもの)である場合は、値を簡単に返すことができます。

Double.ParseまたはDouble.TryParseを使用すると、すでに文字列に含まれている場合に最適ですが、

Double.Parse(o.ToString());

行かなければならない作る文字列が最初に、より高価になる可能性があり、あなたの入力に応じて、解析します。


1
+1:私はあなたの視点を見て、System.Object内の数値でボックス化された数値/文字列を解析するのは非常に簡単で、代わりに大規模な型チェックを行います。しかし、基本的に私は他の答えに同意します:Convert.ToSomething()特に反復のコンテキストでは、Parse / TryParseよりもはるかに高価です
T-moty 2015

私にとって、Convert.ToDouble(o)には、ボックスに含まれているものがすでに数値である場合にいくつかの簡単なアウトがありますが、Convertの本当のキラーは、.TryToDouble(o、out d);がないことです。例外がどれほど高価であるか(そして入力に対してどれほど自信があるかどうか)を考えると、それはConvertの大きな追加費用です。
user1664043 2015

2

Double.TryParseIMO。

処理が簡単です。エラーが発生した場所が正確にわかります。

次に、falseが返された場合(つまり、変換できなかった場合)に適切と思われる方法で対処できます。


2

TryParse()例外を気にすることなく変換の成功または失敗を吐き返すので、私は常にメソッドを使用することを好みました。


2

これは興味深い古い質問です。元の質問でいくつかのことに誰も気づかなかったので、私は答えを追加しています。

Convert.ToDoubleまたはDouble.TryParseのどちらが速いですか?Convert.ToDoubleとDouble.TryParseのどちらが安全ですか?

これらの両方の質問に詳細に答えます(後で答えを更新します)が、最初に:

安全のために、この質問ですべてのプログラマーが見逃したのは、次の行です(私の強調):

数桁の数字であるデータのみを追加します(1000 1000,2 1000,34-コンマはロシアの標準では区切り文字です)。

このコード例が続きます:

Convert.ToDouble(regionData, CultureInfo.CurrentCulture);

ここで興味深いのは、スプレッドシートがロシアの数値形式であるのに、Excelがセルフィールドを正しく入力していない場合、Excelからの値の正しい解釈は何ですか?

速度に関して、2つの例についてもう1つ興味深いことがあります。

catch (InvalidCastException)
{
    // is not a number
}

これにより、次のようなMSILが生成される可能性があります。

catch [mscorlib]System.InvalidCastException 
{
  IL_0023:  stloc.0
  IL_0024:  nop
  IL_0025:  ldloc.0
  IL_0026:  nop
  IL_002b:  nop
  IL_002c:  nop
  IL_002d:  leave.s    IL_002f
}  // end handler
IL_002f: nop
IL_0030: return

この意味で、各プログラムによって実行されたMSIL命令の総数を比較できる可能性があります。これについては、後でこの投稿を更新するときに詳しく説明します。

コードは正しく、明確で、高速でなければならないと思います...この順序で!


1

個人的には、このTryParse方法は読みやすいと思います。実際に使用する方法は、ユースケースによって異なります。エラーをローカルで処理できる場合は、エラーが発生する可能性があり、ブール値TryParseが適切である場合は、そのままにしておきます。例外が発生します。

TryParse例外処理のオーバーヘッドを回避できるので、も高速になると思います。ただし、JonSkeetのMiniBenchなどのベンチマークツールを使用してくださいして、さまざまな可能性を比較してください。


この回答へのフィードバック:質問がより速く、より安全なものを尋ねる場合、回答は「個人的に」で始まるべきではなく、「私は期待する...」のような推測を含めるべきです。これは単なる個人的な考えと解説であり、良い答えではありません。
PandaWood 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.