web-dev-qa-db-ja.com

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

私のアプリケーションは、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);
}
_

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

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

Convert.ToDouble(object)またはConvert.ToDouble(string)を呼び出す方が良いですか?

78
abatishchev

リリースモードで非科学的な簡単なテストを行いました。両方のメソッドに「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への別の投票と、それをバックアップするいくつかの数字があります。

128
Szymon Rozga

まず最初に、double.ParseではなくConvert.ToDoubleを使用します。

ParseTryParseのどちらを使用すべきかについて:不正な入力データがある場合は続行できますか、それとも本当に例外的な条件ですか?例外的な場合は、Parseを使用し、入力が悪い場合は爆破させます。予期されていて、きれいに処理できる場合は、TryParseを使用します。

46
Jon Skeet

.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_を直接実行する方が高速です。

8
Jeff Moser

入力が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.

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

7
Chase

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

7
Aaron Palmer

私は一般的にConvertクラスを回避しようとします(意味:私はそれを使用しません)私はそれが非常に混乱していると思うので:Convertは同じコードで発生する意味的に非常に異なる変換。これにより、プログラマーが正確に何が起こっているかを制御することが難しくなります。

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

7
Konrad Rudolph

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

Convert.ToDouble(o);

oが既にDouble(またはintまたは容易にキャスト可能なもの)であれば、値を簡単に返すことができます。

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

Double.Parse(o.ToString());

make最初に解析される文字列であり、入力に応じてより高価になる可能性があります。

3
user1664043

Double.TryParse IMO。

処理は簡単です。エラーが発生した場所を正確に知ることができます。

次に、falseを返した場合(つまり変換できなかった場合)にどのように適合するかを処理できます。

2
Damien

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

2
TheTXI

これは興味深い古い質問です。元の質問でいくつかのことに気づいた人がいなかったため、回答を追加します。

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

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

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

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

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

Convert.ToDouble(regionData, CultureInfo.CurrentCulture);

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

以下に、速度に関する2つの例の興味深い点を示します。

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
John Zabroski

個人的には、TryParseメソッドは読みやすいと思いますが、実際に使用したいのはユースケース次第です。エラーをローカルで処理できる場合、エラーとTryParseは良いですが、それ以外の場合は例外を飛ばしたいかもしれません。

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

1
David Schmitt