C#でstringをdoubleに変換する方法|Parse・TryParse・小数点エラー対策まで解説
はじめに
C#でフォーム入力、CSV、設定ファイル、APIレスポンスなどを扱うと、string型の文字列をdouble型の数値へ変換する場面がよくあります。
たとえば、文字列の"12.5"を計算に利用するには、そのままではなく12.5というdouble型の値に変換しなければなりません。
C#でstringをdoubleに変換する代表的な方法は、次の3つです。
double.Parsedouble.TryParseConvert.ToDouble
どの方法でも数値変換はできますが、変換できない文字列を渡した場合の挙動や、nullを扱う場合の結果が異なります。また、小数点や桁区切り記号は実行環境のカルチャによって解釈が変わるため、注意が必要です。
この記事では、C#でstringをdoubleに変換する方法を、サンプルコード付きで解説します。Parse・TryParse・Convert.ToDoubleの違いに加え、小数点やカンマによるエラーへの対処法、実務で使える変換パターンも紹介します。
1. C#でstringをdoubleに変換する基本
1-1. stringからdoubleへの変換が必要になる場面
C#では、見た目が数字であっても、string型の値をそのまま数値計算に使用することはできません。
string text = "12.5";// string型なので数値の加算にはならないstring result = text + "1";
Console.WriteLine(result); // 12.51
上記のコードでは、"12.5"と"1"が文字列として連結されるため、結果は"12.51"になります。
数値として加算するには、stringをdoubleへ変換します。
string text = "12.5";double number = double.Parse(text);double result = number + 1;
Console.WriteLine(result); // 13.5
stringからdoubleへの変換が必要になる代表的な場面は、次のとおりです。
テキストボックスに入力された小数を計算する
CSVから読み込んだ価格や測定値を数値として扱う
APIから文字列として返された数値を処理する
設定ファイルの数値をプログラム内で利用する
データベースから取得した文字列を数値に変換する
外部から受け取る文字列には、空文字や不正な文字が含まれる可能性があります。そのため、値の出どころに応じて変換方法を使い分けることが重要です。
1-2. 変換に使う主な方法はParse・TryParse・Convert.ToDouble
C#でstringをdoubleに変換する主な方法は、次の3つです。
string text = "12.5";double value1 = double.Parse(text);
bool success = double.TryParse(text, out double value2);
double value3 = Convert.ToDouble(text);
それぞれの特徴を簡単にまとめると、次のようになります。
| 方法 | 変換失敗時 | nullを渡した場合 | 主な用途 |
|---|---|---|---|
double.Parse | 例外が発生する | 例外が発生する | 必ず正しい数値だと保証できる文字列 |
double.TryParse | falseを返す | falseを返す | ユーザー入力や外部データ |
Convert.ToDouble | 不正な文字列では例外が発生する | 0を返す | nullを0として扱いたい処理 |
単純に変換できるかどうかだけでなく、変換できなかったときにどのような処理をしたいかを考えて選択しましょう。
1-3. まず結論:安全に変換するならTryParseがおすすめ
ユーザー入力やCSVなど、内容が常に正しいとは限らない文字列を変換する場合は、double.TryParseがおすすめです。
string input = "12.5";if (double.TryParse(input, out double value)){Console.WriteLine($"変換成功: {value}");}else{Console.WriteLine("数値を入力してください。");}
TryParseは変換に失敗しても例外を発生させず、戻り値としてfalseを返します。そのため、正常な入力と不正な入力を安全に分岐できます。
一方、文字列が必ず正しい数値形式であることが保証されている場合は、コードを簡潔に書けるdouble.Parseも選択肢になります。
2. double.Parseでstringをdoubleに変換する方法
2-1. double.Parseの基本構文
double.Parseは、数値形式の文字列をdouble型へ変換するメソッドです。
基本構文は次のとおりです。
double 変数名 = double.Parse(文字列);実際のコードでは、次のように記述します。
string text = "123.45";double value = double.Parse(text);Console.WriteLine(value); // 123.45
変換対象が有効な数値形式であれば、対応するdouble型の値が返されます。
2-2. double.Parseを使ったサンプルコード
整数形式の文字列もdoubleへ変換できます。
string text = "100";double value = double.Parse(text);Console.WriteLine(value); // 100Console.WriteLine(value.GetType()); // System.Double
負の値や指数表記も変換可能です。
string negativeText = "-25.8";string exponentText = "1.5E3";double negativeValue = double.Parse(negativeText);double exponentValue = double.Parse(exponentText);
Console.WriteLine(negativeValue); // -25.8Console.WriteLine(exponentValue); // 1500
前後に一般的な空白が含まれていても、標準的な数値形式として解釈できれば変換できます。
string text = " 12.5 ";double value = double.Parse(text);Console.WriteLine(value); // 12.5
ただし、利用できる小数点や桁区切り記号は、実行環境のカルチャ設定によって異なります。
2-3. Parseで変換できる文字列と変換できない文字列
double.Parseで変換できる代表的な文字列は、次のとおりです。
double.Parse("100"); // 整数形式double.Parse("12.5"); // 小数形式double.Parse("-8.25"); // 負の値double.Parse("+10.5"); // 正の符号付きdouble.Parse("1.2E3"); // 指数表記double.Parse(" 25.0 "); // 前後に空白一方、次のような文字列は通常、そのままでは変換できません。
double.Parse(""); // 空文字double.Parse("abc"); // 数字以外double.Parse("12.5kg"); // 単位を含むdouble.Parse("12.5"); // 全角数字を含む変換できない文字列をdouble.Parseへ渡すと、例外が発生します。
2-4. FormatExceptionが発生する原因
FormatExceptionは、文字列が有効な数値形式ではない場合に発生します。
string text = "12.5kg";double value = double.Parse(text);"12.5kg"には数値以外の文字が含まれているため、doubleへ直接変換できません。
例外を処理する場合は、try-catchを使用できます。
string text = "12.5kg";try{double value = double.Parse(text);Console.WriteLine(value);}catch (FormatException){Console.WriteLine("数値形式が正しくありません。");}
また、nullを渡した場合は、数値形式の問題ではなく引数が存在しないため、ArgumentNullExceptionが発生します。
string? text = null;double value = double.Parse(text!);入力値が不確実な処理で毎回例外を捕捉するよりも、double.TryParseを使って変換可能か判定するほうが適しています。
2-5. Parseを使うべきケース
double.Parseが適しているのは、変換対象が必ず正しい数値形式であると保証できるケースです。
たとえば、プログラム内部で定義した固定値を変換する場合が該当します。
const string TaxRateText = "0.1";double taxRate = double.Parse(TaxRateText,System.Globalization.CultureInfo.InvariantCulture);正しい値であることが保証されていれば、変換失敗時に例外を発生させることで、設定ミスやプログラム上の不具合を早期に発見できます。
反対に、ユーザー入力や外部ファイルなど、不正な値が入り得る場面ではTryParseを選ぶのが基本です。
3. double.TryParseで安全にstringをdoubleへ変換する方法
3-1. double.TryParseの基本構文
double.TryParseは、文字列をdoubleへ変換できるか試すメソッドです。
基本構文は次のとおりです。
bool 成否 = double.TryParse(文字列, out double 結果);変換に成功するとtrue、失敗するとfalseを返します。変換後の値はout引数で受け取ります。
string text = "123.45";bool success = double.TryParse(text, out double value);
Console.WriteLine(success); // TrueConsole.WriteLine(value); // 123.45
変換に失敗した場合、out引数の値は0になります。
string text = "abc";bool success = double.TryParse(text, out double value);
Console.WriteLine(success); // FalseConsole.WriteLine(value); // 0
ただし、戻り値を確認せずにvalueだけを使用すると、本当に入力が0だったのか、変換に失敗して0になったのか区別できません。必ず戻り値を確認しましょう。
3-2. TryParseを使ったサンプルコード
一般的には、if文の条件内でTryParseを呼び出します。
string input = "98.6";if (double.TryParse(input, out double temperature)){Console.WriteLine($"変換後の値: {temperature}");}else{Console.WriteLine("変換できませんでした。");}
入力が"98.6"であれば変換に成功し、temperatureへ98.6が代入されます。
入力が不正な場合も、プログラムは例外で停止しません。
string input = "不明";if (double.TryParse(input, out double value)){Console.WriteLine(value);}else{Console.WriteLine("有効な数値ではありません。");}
3-3. 変換に成功した場合と失敗した場合の処理
TryParseを使うと、変換結果に応じた処理を明確に分けられます。
Console.Write("身長を入力してください: ");string? input = Console.ReadLine();if (double.TryParse(input, out double height)){Console.WriteLine($"入力された身長は{height}cmです。");}else{Console.WriteLine("身長は半角数字で入力してください。");}
範囲チェックを組み合わせることもできます。
string input = "175.5";if (!double.TryParse(input, out double height)){Console.WriteLine("数値形式が正しくありません。");}else if (height <= 0 || height > 300){Console.WriteLine("入力可能な範囲を超えています。");}else{Console.WriteLine($"身長: {height}cm");}
TryParseが判定するのは、文字列を数値へ変換できるかどうかです。業務上許可される値かどうかは、別途バリデーションする必要があります。
3-4. 例外を出さずに変換できるメリット
不正な入力が日常的に発生する処理では、例外を通常の分岐として使うべきではありません。
次のコードは動作しますが、入力ミスが起こるたびに例外が発生します。
try{double value = double.Parse(input);}catch (FormatException){Console.WriteLine("入力エラーです。");}TryParseを使えば、同じ処理をより意図が伝わりやすい形で記述できます。
if (!double.TryParse(input, out double value)){Console.WriteLine("入力エラーです。");}TryParseには、次のメリットがあります。
不正な入力でも例外が発生しない
成功と失敗を
bool値で判断できる入力チェックの意図がコードから分かりやすい
多数のデータを処理する場合に例外処理の負担を避けられる
3-5. ユーザー入力や外部データにはTryParseが適している理由
ユーザー入力や外部データは、プログラム側で完全に内容を保証できません。
たとえば、入力フォームには次のような値が送られる可能性があります。
空文字
空白だけの文字列
数字以外の文字列
全角数字
単位付きの値
想定と異なる小数点記号
非常に大きい数値
TryParseを使えば、こうした値を例外にせず、入力エラーとして処理できます。
string? input = GetUserInput();if (string.IsNullOrWhiteSpace(input)){Console.WriteLine("値を入力してください。");}else if (!double.TryParse(input, out double value)){Console.WriteLine("有効な数値を入力してください。");}else{Console.WriteLine($"登録する値: {value}");}
外部から受け取った値には、原則としてTryParseとバリデーションを組み合わせると安全です。
4. Convert.ToDoubleでstringをdoubleに変換する方法
4-1. Convert.ToDoubleの基本構文
Convert.ToDoubleも、文字列をdouble型へ変換できます。
基本構文は次のとおりです。
double 変数名 = Convert.ToDouble(文字列);使用例は次のとおりです。
string text = "123.45";double value = Convert.ToDouble(text);Console.WriteLine(value); // 123.45
正常な数値文字列に対する結果は、double.Parseとほぼ同じです。
4-2. Convert.ToDoubleを使ったサンプルコード
string text = "-45.6";double value = Convert.ToDouble(text);Console.WriteLine(value); // -45.6
カルチャを明示するオーバーロードもあります。
using System.Globalization;string text = "12.34";
double value = Convert.ToDouble(text,CultureInfo.InvariantCulture);
Console.WriteLine(value); // 12.34
変換できない文字列を渡すと、FormatExceptionが発生します。
string text = "abc";double value = Convert.ToDouble(text);そのため、Convert.ToDoubleも不正な入力を自動的に安全処理してくれるわけではありません。
4-3. nullを変換した場合の挙動
Convert.ToDoubleの特徴は、nullを渡した場合に0を返すことです。
string? text = null;double value = Convert.ToDouble(text);Console.WriteLine(value); // 0
これはdouble.Parseとの大きな違いです。
string? text = null;// ArgumentNullExceptionが発生するdouble value = double.Parse(text!);
ただし、nullを0として扱ってよいかどうかは、アプリケーションの仕様によります。
「値がない」と「数値の0」は意味が異なることがあります。値が存在しない状態を保持したい場合は、double?を利用したほうが適切です。
string? text = null;double? value = double.TryParse(text, out double parsed)? parsed: null;
Console.WriteLine(value is null); // True
4-4. Parseとの違い
double.ParseとConvert.ToDoubleは、有効な数値文字列に対しては同様の結果を返します。
string text = "25.5";double value1 = double.Parse(text);double value2 = Convert.ToDouble(text);
Console.WriteLine(value1); // 25.5Console.WriteLine(value2); // 25.5
主な違いはnullの扱いです。
string? text = null;// 例外が発生する// double value1 = double.Parse(text!);
// 0が返るdouble value2 = Convert.ToDouble(text);
空文字の場合は、Convert.ToDoubleでもFormatExceptionが発生します。
string text = "";double value = Convert.ToDouble(text);Convert.ToDoubleが0を返すのはnullの場合であり、空文字や不正な文字列まで0へ変換されるわけではありません。
4-5. Convert.ToDoubleを使うべきケース
Convert.ToDoubleは、次のようなケースで利用できます。
nullを0として扱う仕様になっているobject型など、複数の型を数値へ変換したいConvertクラスで変換処理を統一している
たとえば、object型の値をdoubleへ変換できます。
object value = "12.5";double number = Convert.ToDouble(value);Console.WriteLine(number); // 12.5
一方、文字列入力の妥当性を確認したい場合は、Convert.ToDoubleよりもdouble.TryParseが適しています。
5. 小数点やカンマで起こる変換エラーの対策
5-1. 小数点「.」とカンマ「,」でエラーが起きる理由
数値の小数点や桁区切りに使う記号は、国や地域によって異なります。
日本やアメリカでは、一般的にピリオドを小数点、カンマを桁区切りとして使用します。
1,234.56一方、一部のヨーロッパ圏では、カンマを小数点、ピリオドを桁区切りとして使用します。
1.234,56C#のParseやTryParseは、カルチャを指定しなければ、通常は実行環境の現在のカルチャを使って文字列を解釈します。
そのため、同じ文字列でも、実行する環境によって結果が変わったり、変換に失敗したりする可能性があります。
5-2. CultureInfoによる数値形式の違い
数値形式を明示するには、System.Globalization.CultureInfoを使用します。
using System.Globalization;string text = "1,234.56";
double value = double.Parse(text,CultureInfo.GetCultureInfo("en-US"));
Console.WriteLine(value); // 1234.56
ドイツ語圏の形式を扱う場合は、de-DEなどを指定します。
using System.Globalization;string text = "1.234,56";
double value = double.Parse(text,CultureInfo.GetCultureInfo("de-DE"));
Console.WriteLine(value); // 1234.56
カルチャを指定することで、入力文字列がどの地域の数値形式なのかを明確にできます。
5-3. CultureInfo.InvariantCultureを使った変換方法
CultureInfo.InvariantCultureは、特定の国や地域に依存しない固定の数値形式を使用するためのカルチャです。
設定ファイル、CSV、APIなど、機械同士で値をやり取りする場合に適しています。
using System.Globalization;string text = "1234.56";
double value = double.Parse(text,CultureInfo.InvariantCulture);
Console.WriteLine(value); // 1234.56
TryParseでも使用できます。
using System.Globalization;string text = "1234.56";
bool success = double.TryParse(text,NumberStyles.Float,CultureInfo.InvariantCulture,out double value);
if (success){Console.WriteLine(value);}
桁区切りカンマも許可する場合は、NumberStyles.AllowThousandsを追加します。
using System.Globalization;string text = "1,234.56";
bool success = double.TryParse(text,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out double value);
Console.WriteLine(success); // TrueConsole.WriteLine(value); // 1234.56
5-4. 日本語環境と英語環境で結果が変わるケース
日本語環境と英語環境は、どちらも一般的にピリオドを小数点として扱います。そのため、"12.5"のような値は通常どちらでも同じように変換できます。
しかし、すべての環境が同じ形式とは限りません。
string text = "12,5";double value = double.Parse(text);この文字列は、カンマを小数点として使うカルチャでは12.5と解釈される可能性があります。一方、カンマを桁区切りとして扱うカルチャでは、異なる値として解釈されたり、指定したスタイルによっては変換に失敗したりします。
保存データや通信データの形式が決まっている場合は、現在のカルチャに任せず、必ず対応するCultureInfoを指定しましょう。
using System.Globalization;string text = "12.5";
if (double.TryParse(text,NumberStyles.Float,CultureInfo.InvariantCulture,out double value)){Console.WriteLine(value);}
画面上でユーザーが入力する値はユーザーのカルチャ、APIや設定ファイルではInvariantCultureというように、用途に応じた使い分けが必要です。
5-5. NumberStylesを指定して柔軟に変換する方法
NumberStylesを指定すると、許可する数値形式を細かく制御できます。
using System.Globalization;string text = "1,234.56";
NumberStyles styles =NumberStyles.AllowDecimalPoint |NumberStyles.AllowThousands |NumberStyles.AllowLeadingSign |NumberStyles.AllowLeadingWhite |NumberStyles.AllowTrailingWhite;
bool success = double.TryParse(text,styles,CultureInfo.InvariantCulture,out double value);
Console.WriteLine(success); // TrueConsole.WriteLine(value); // 1234.56
一般的な浮動小数点数を扱う場合は、NumberStyles.Floatを利用すると便利です。
using System.Globalization;string text = "-1.25E3";
bool success = double.TryParse(text,NumberStyles.Float,CultureInfo.InvariantCulture,out double value);
Console.WriteLine(value); // -1250
NumberStyles.Floatには、符号、小数点、指数表記、前後の空白などが含まれます。ただし、桁区切り記号を許可するには、NumberStyles.AllowThousandsを追加します。
NumberStyles styles =NumberStyles.Float |NumberStyles.AllowThousands;許可する形式を必要最小限にすると、想定外の入力を誤って数値として受け入れるリスクを減らせます。
6. stringをdoubleに変換できない場合の原因と対処法
6-1. 空文字やnullが含まれている
nullや空文字は、通常の数値として変換できません。
string? value1 = null;string value2 = "";string value3 = " ";変換前にstring.IsNullOrWhiteSpaceでチェックできます。
string? input = GetInput();if (string.IsNullOrWhiteSpace(input)){Console.WriteLine("値が入力されていません。");}else if (double.TryParse(input, out double value)){Console.WriteLine(value);}else{Console.WriteLine("数値形式が正しくありません。");}
Convert.ToDouble(null)は0を返しますが、「未入力」と「0」を区別したい場合には使用しないほうがよいでしょう。
6-2. 数字以外の文字が含まれている
単位や通貨記号などが含まれている文字列は、そのままでは変換できない場合があります。
string text = "12.5kg";単位が必ず末尾に付く仕様であれば、単位を取り除いてから変換できます。
string text = "12.5kg";string normalized = text.Replace("kg", "").Trim();if (double.TryParse(normalized,System.Globalization.NumberStyles.Float,System.Globalization.CultureInfo.InvariantCulture,out double value)){Console.WriteLine(value); // 12.5}
ただし、無条件に文字を削除すると不正な値を受け入れる可能性があります。入力形式を明確に定義し、その形式に沿って検証することが大切です。
6-3. 全角数字や記号が含まれている
日本語入力では、全角数字が含まれることがあります。
123.45このような文字列は、一般的なdouble.TryParseでは変換できない場合があります。
全角文字を半角へ正規化する方法の一つが、Microsoft.VisualBasic.Strings.StrConvです。
using Microsoft.VisualBasic;using System.Globalization;string input = "123.45";string normalized = Strings.StrConv(input,VbStrConv.Narrow,0x0411);
bool success = double.TryParse(normalized,NumberStyles.Float,CultureInfo.InvariantCulture,out double value);
Console.WriteLine(success); // TrueConsole.WriteLine(value); // 123.45
正規化を行う場合も、変換後に値の範囲や形式を検証してください。
対象文字が限定されている場合は、明示的に置換する方法もあります。
static string ConvertFullWidthNumbers(string value){return value.Replace('0', '0').Replace('1', '1').Replace('2', '2').Replace('3', '3').Replace('4', '4').Replace('5', '5').Replace('6', '6').Replace('7', '7').Replace('8', '8').Replace('9', '9').Replace('.', '.').Replace('-', '-');}6-4. 桁区切りカンマが含まれている
"1,234.56"のような文字列を変換する場合は、カルチャとNumberStylesを適切に指定します。
using System.Globalization;string input = "1,234.56";
bool success = double.TryParse(input,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out double value);
Console.WriteLine(success); // TrueConsole.WriteLine(value); // 1234.56
単純にカンマを削除する方法もあります。
string normalized = input.Replace(",", "");ただし、カンマが小数点として使われる地域のデータには適用できません。
たとえば"12,5"をカンマ削除すると"125"になり、本来の12.5とは異なる値になります。データの数値形式が分かっている場合は、文字列置換ではなくCultureInfoで解釈するほうが安全です。
6-5. 指数表記や負の値を扱う場合
doubleは、負の値や指数表記を扱えます。
using System.Globalization;string negativeText = "-12.5";string exponentText = "1.23E4";
double.TryParse(negativeText,NumberStyles.Float,CultureInfo.InvariantCulture,out double negativeValue);
double.TryParse(exponentText,NumberStyles.Float,CultureInfo.InvariantCulture,out double exponentValue);
Console.WriteLine(negativeValue); // -12.5Console.WriteLine(exponentValue); // 12300
負の値を業務上許可しない場合は、変換後にチェックします。
if (!double.TryParse(input, out double value)){Console.WriteLine("数値ではありません。");}else if (value < 0){Console.WriteLine("負の値は入力できません。");}else{Console.WriteLine(value);}数値形式として正しいことと、業務上利用可能であることは別の問題です。
6-6. 変換前に文字列をチェック・整形する方法
変換前の基本的な処理として、前後の空白を取り除くTrimがあります。
string input = " 12.5 ";string normalized = input.Trim();空文字やnullのチェックと組み合わせると、次のように記述できます。
using System.Globalization;static bool TryConvertToDouble(string? input, out double value){value = default;
if (string.IsNullOrWhiteSpace(input)){return false;}string normalized = input.Trim();return double.TryParse(normalized,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out value);
}
利用例は次のとおりです。
if (TryConvertToDouble(" 1,234.56 ", out double value)){Console.WriteLine(value); // 1234.56}文字列の整形では、入力仕様にない文字を安易に削除しないよう注意してください。誤入力を正しい値に見せかけてしまう可能性があります。
7. Parse・TryParse・Convert.ToDoubleの違いと使い分け
7-1. 3つの変換方法の比較表
double.Parse、double.TryParse、Convert.ToDoubleの違いは次のとおりです。
| 項目 | double.Parse | double.TryParse | Convert.ToDouble |
| 戻り値 | 変換後のdouble | 成功・失敗を表すbool | 変換後のdouble |
| 結果の受け取り方 | 戻り値 | out引数 | 戻り値 |
| 不正な文字列 | 例外 | false | 例外 |
| 空文字 | 例外 | false | 例外 |
| null | 例外 | false | 0 |
| カルチャ指定 | 可能 | 可能 | 可能 |
| 主な用途 | 正常値が保証されたデータ | ユーザー入力・外部データ | nullを0として扱う変換 |
7-2. 例外処理が必要なParse
double.Parseは、変換できなければ例外を発生させます。
string input = "abc";try{double value = double.Parse(input);Console.WriteLine(value);}catch (FormatException){Console.WriteLine("数値形式が不正です。");}
正常な値が保証されていない場合は、FormatExceptionなどを考慮しなければなりません。
一方、設定値など「不正な値なら処理を続けるべきではない」という場面では、例外を発生させるParseが適する場合もあります。
7-3. 安全性が高いTryParse
TryParseは、変換できない文字列を通常の入力エラーとして扱えます。
if (!double.TryParse(input, out double value)){Console.WriteLine("有効な数値を入力してください。");return;}Console.WriteLine($"変換結果: {value}");
外部から受け取る文字列には、不正な値が含まれることを前提に設計する必要があります。そのため、実務ではTryParseを使用する場面が多くなります。
7-4. nullに強いConvert.ToDouble
Convert.ToDoubleは、nullを渡しても例外を発生させず、0を返します。
string? input = null;double value = Convert.ToDouble(input);Console.WriteLine(value); // 0
ただし、これは常に「安全」という意味ではありません。
nullがデータ欠損を表している場合、0へ変換すると欠損値と実際の0を区別できなくなります。仕様上、nullを0として扱うことが明確な場合に使用しましょう。
7-5. 実務でおすすめの使い分け
実務では、次の基準で使い分けると分かりやすくなります。
ユーザー入力や外部データ
double.TryParse不正な値が入る可能性があるため、原則としてTryParseを使用します。
プログラム内部の固定値や検証済みデータ
double.Parse値が正しいことを保証でき、不正な場合は例外として検出したいケースに適しています。
nullを0として処理する仕様
Convert.ToDoublenullと0を区別する必要がない場合に利用できます。
迷った場合は、変換失敗を安全に処理できるdouble.TryParseを選ぶとよいでしょう。
8. 実務で使えるstringからdoubleへの変換パターン
8-1. 入力フォームの文字列をdoubleに変換する
入力フォームでは、空文字や不正な値を考慮します。
ASP.NET Coreでフォーム入力を処理するイメージは次のとおりです。
using System.Globalization;string? input = Request.Form["height"];
if (string.IsNullOrWhiteSpace(input)){ModelState.AddModelError("height", "身長を入力してください。");}else if (!double.TryParse(input,NumberStyles.Float,CultureInfo.CurrentCulture,out double height)){ModelState.AddModelError("height", "有効な数値を入力してください。");}else if (height <= 0 || height > 300){ModelState.AddModelError("height", "身長は0より大きく300以下で入力してください。");}else{// heightを保存する処理}
画面入力では、利用者の地域設定に合わせてCultureInfo.CurrentCultureを使う方法があります。
ただし、アプリケーション全体で入力形式をピリオド区切りに統一している場合は、InvariantCultureなど、仕様に対応したカルチャを指定してください。
8-2. CSVから読み込んだ文字列をdoubleに変換する
CSVでは、ファイルの数値形式をあらかじめ決めておくことが重要です。
using System.Globalization;string[] columns = { "商品A", "1,234.56" };string priceText = columns[1];
if (double.TryParse(priceText,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out double price)){Console.WriteLine($"価格: {price}");}else{Console.WriteLine($"価格を変換できません: {priceText}");}
複数行を処理する場合は、変換できなかった行番号や元の値を記録すると、原因を確認しやすくなります。
for (int i = 0; i < rows.Count; i++){string priceText = rows[i].Price;if (!double.TryParse(priceText,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out double price)){Console.WriteLine($"{i + 1}行目の価格が不正です: {priceText}");continue;}ProcessPrice(price);
}
CSVの区切り文字がカンマの場合、数値内の桁区切りカンマは引用符で囲まれていることがあります。単純なSplit(',')では正しく分割できないため、本格的なCSV処理ではCSVパーサーの利用も検討してください。
8-3. APIレスポンスの文字列をdoubleに変換する
APIで数値が文字列として返される場合は、API仕様で定められた数値形式を使います。
using System.Globalization;string? temperatureText = response.Temperature;
if (!double.TryParse(temperatureText,NumberStyles.Float,CultureInfo.InvariantCulture,out double temperature)){throw new InvalidOperationException($"APIの温度を変換できません: {temperatureText}");}
APIやJSONでは、可能であれば最初から数値型として受け取る設計が望ましいです。
public sealed class WeatherResponse{public double Temperature { get; set; }}API仕様上、数値が文字列として返る場合は、TryParseによる検証とエラー処理を行いましょう。
8-4. null許容型double?として扱う
未入力や変換失敗をnullとして扱いたい場合は、double?を使用します。
static double? ParseNullableDouble(string? input){if (string.IsNullOrWhiteSpace(input)){return null;}return double.TryParse(input, out double value)? value: null;
}
使用例は次のとおりです。
double? value = ParseNullableDouble("12.5");if (value.HasValue){Console.WriteLine(value.Value);}else{Console.WriteLine("値がありません。");}
ただし、この実装では「未入力」と「不正な文字列」がどちらもnullになります。両者を区別する必要がある場合は、結果を表す独自の型やエラー情報を返す設計を検討してください。
カルチャを固定した実装は次のようになります。
using System.Globalization;static double? ParseNullableDouble(string? input){if (string.IsNullOrWhiteSpace(input)){return null;}
return double.TryParse(input,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out double value)? value: null;
}
8-5. 共通メソッド化して再利用する
同じ変換処理を複数箇所で使用する場合は、共通メソッドにまとめると保守しやすくなります。
using System.Globalization;public static class NumberParser{public static bool TryParseDouble(string? input,out double value){value = default;
if (string.IsNullOrWhiteSpace(input)){return false;}return double.TryParse(input.Trim(),NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out value);}
}
利用側は、変換条件を意識せずに呼び出せます。
if (NumberParser.TryParseDouble("1,234.56", out double value)){Console.WriteLine(value);}else{Console.WriteLine("変換に失敗しました。");}エラーメッセージも返したい場合は、次のような実装が可能です。
using System.Globalization;public static class NumberParser{public static bool TryParseDouble(string? input,out double value,out string? errorMessage){value = default;errorMessage = null;
if (string.IsNullOrWhiteSpace(input)){errorMessage = "値が入力されていません。";return false;}if (!double.TryParse(input.Trim(),NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out value)){errorMessage = "数値形式が正しくありません。";return false;}return true;}
}
if (!NumberParser.TryParseDouble(input,out double value,out string? errorMessage)){Console.WriteLine(errorMessage);return;}Console.WriteLine(value);
共通メソッド化すると、カルチャや許可する数値形式を一元管理できます。
9. C#でstringをdoubleに変換する際の注意点
9-1. doubleは小数計算で誤差が出る場合がある
doubleは浮動小数点数であり、多くの小数を2進数で正確に表現できません。そのため、計算結果に微小な誤差が含まれる場合があります。
double value = 0.1 + 0.2;Console.WriteLine(value);Console.WriteLine(value == 0.3); // Falseになる場合がある
0.1や0.2は、doubleの内部表現では近似値として保持されます。
小数を比較する場合は、一定の許容誤差を設ける方法があります。
double actual = 0.1 + 0.2;double expected = 0.3;double tolerance = 0.0000001;bool isEqual = Math.Abs(actual - expected) < tolerance;
Console.WriteLine(isEqual); // True
必要な精度や値の範囲に応じて、適切な型と比較方法を選択してください。
9-2. 金額計算にはdecimalを検討する
金額のように10進数としての正確性が重要な値には、doubleよりdecimalが適しています。
string priceText = "1234.56";if (decimal.TryParse(priceText, out decimal price)){Console.WriteLine(price);}
decimalは10進数の計算に適しているため、金額計算で意図しない丸め誤差を避けやすくなります。
decimal total = 0.1m + 0.2m;Console.WriteLine(total); // 0.3Console.WriteLine(total == 0.3m); // True
科学技術計算、座標、測定値などではdouble、金額や会計処理ではdecimalを検討するのが一般的です。
9-3. 例外処理に頼りすぎない
不正なユーザー入力をParseとtry-catchだけで処理すると、例外が通常の制御フローになってしまいます。
try{double value = double.Parse(input);}catch (FormatException){// 入力ミスを処理}入力ミスが予想される場面では、TryParseを使用します。
if (!double.TryParse(input, out double value)){Console.WriteLine("数値を入力してください。");return;}例外は、予期しない障害や処理を続行できない問題に利用し、想定内の入力エラーは戻り値で処理するとコードの意図が明確になります。
9-4. 文化圏に依存しないコードを書く
カルチャを指定しない変換は、実行環境によって挙動が変わる可能性があります。
double value = double.Parse("12.5");ローカル環境では動作しても、異なる地域設定のサーバーでは同じ結果にならない可能性があります。
API、CSV、設定ファイルなど、固定形式のデータにはカルチャを明示します。
using System.Globalization;double value = double.Parse("12.5",CultureInfo.InvariantCulture);
画面入力ではユーザーのカルチャ、内部データや通信データではInvariantCultureなど、データの用途に合わせて指定しましょう。
9-5. 入力値のバリデーションを行う
TryParseが成功しても、その値が業務上正しいとは限りません。
string input = "-100";if (double.TryParse(input, out double price)){Console.WriteLine(price); // 数値としては変換できる}
価格として負の値を許可しない場合は、追加のチェックが必要です。
if (!double.TryParse(input, out double price)){Console.WriteLine("数値形式が正しくありません。");}else if (price < 0){Console.WriteLine("価格には0以上の値を指定してください。");}else if (price > 1_000_000){Console.WriteLine("価格が上限を超えています。");}else{Console.WriteLine($"登録価格: {price}");}状況に応じて、次の項目を検証します。
必須入力か
数値として変換できるか
最小値と最大値の範囲内か
負の値を許可するか
小数点以下の桁数は適切か
NaNや無限大を許可するか
double.TryParseは、NaNやInfinityなどを数値として受け入れる場合があります。通常の有限値だけを許可する場合は、double.IsFiniteで確認できます。
using System.Globalization;string input = "NaN";
if (!double.TryParse(input,NumberStyles.Float,CultureInfo.InvariantCulture,out double value)){Console.WriteLine("数値形式が正しくありません。");}else if (!double.IsFinite(value)){Console.WriteLine("有限の数値を入力してください。");}else{Console.WriteLine(value);}
変換処理と業務上のバリデーションを組み合わせることで、安全な入力処理を実装できます。
まとめ
C#でstringをdoubleに変換する主な方法は、double.Parse、double.TryParse、Convert.ToDoubleの3つです。
変換対象が必ず正しい数値文字列である場合は、double.Parseを使用できます。ただし、変換できない文字列やnullを渡すと例外が発生します。
ユーザー入力、CSV、APIレスポンスなど、内容が保証されていない文字列にはdouble.TryParseが適しています。変換に失敗しても例外が発生せず、戻り値のtrueまたはfalseで結果を判断できます。
Convert.ToDoubleは、nullを0として扱う点が特徴です。ただし、不正な文字列や空文字では例外が発生するため、入力チェックの代わりにはなりません。
また、小数点やカンマの解釈はカルチャによって異なります。API、CSV、設定ファイルなど、形式が固定されたデータを扱う場合は、CultureInfo.InvariantCultureや適切なCultureInfoを明示しましょう。
実務で安全に変換する基本形は、次のコードです。
using System.Globalization;bool success = double.TryParse(input,NumberStyles.Float | NumberStyles.AllowThousands,CultureInfo.InvariantCulture,out double value);
if (!success){Console.WriteLine("有効な数値を入力してください。");}
変換できるかどうかだけでなく、値の範囲、負数の可否、NaNや無限大、小数計算の誤差も考慮することが重要です。金額を扱う場合は、doubleではなくdecimalの利用も検討してください。

