C#で文字列をdecimalに変換する方法|decimal.Parse・TryParseの使い方とエラー対策

はじめに

C#で文字列を数値に変換するとき、整数ならint.Parse、小数を扱うならdecimal.Parsedecimal.TryParseを使います。

特に金額、料金、税率、割合、数量など、誤差をできるだけ避けたい数値を扱う場合はdecimal型がよく使われます。

たとえば、次のような文字列をdecimal型に変換したい場面があります。

C#
"123.45"
"1000"
"-250.5"
"1,234.56"

このような文字列を変換する方法として、C#では主に次の2つを使います。

C#
decimal.Parse()
decimal.TryParse()

decimal.Parseは、変換できない文字列が渡されると例外が発生します。一方、decimal.TryParseは変換に成功したかどうかをtrueまたはfalseで判定できます。

この記事では、C#で文字列をdecimalに変換する基本から、decimal.Parsedecimal.TryParseの違い、エラー対策、カンマや通貨記号を含む文字列の変換、CultureInfoを使った環境差への対応まで解説します。

1. C#で文字列をdecimalに変換する基本

C#で文字列をdecimalに変換する場合、基本的にはdecimal.Parseまたはdecimal.TryParseを使います。

C#
string text = "123.45";
decimal value = decimal.Parse(text);

このコードでは、文字列"123.45"decimal型の数値123.45に変換しています。

ただし、文字列が必ず正しい数値形式であるとは限りません。

C#
string text = "abc";
decimal value = decimal.Parse(text); // エラー

このような場合は例外が発生します。そのため、実務では入力値の信頼性に応じてParseTryParseを使い分けることが重要です。

1-1. decimal.Parseとは

decimal.Parseは、文字列をdecimal型に変換するためのメソッドです。

C#
string text = "100.5";
decimal value = decimal.Parse(text);

Console.WriteLine(value);

実行結果は次のようになります。

C#
100.5

decimal.Parseは、変換対象の文字列が正しい数値形式であることを前提にしています。

そのため、次のような文字列であれば変換できます。

C#
"100"
"100.5"
"-100.5"
"1,000.5"

一方で、次のような文字列は変換できません。

C#
"abc"
""
null
"100円"

ただし、カンマ区切りや通貨記号などは、指定するNumberStylesCultureInfoによって変換できる場合があります。

1-2. decimal.TryParseとは

decimal.TryParseは、文字列をdecimalに変換できるかどうかを安全に判定するためのメソッドです。

C#
string text = "123.45";

bool result = decimal.TryParse(text, out decimal value);

if (result)
{
Console.WriteLine($"変換成功: {value}");
}
else
{
Console.WriteLine("変換失敗");
}

TryParseは、変換に成功するとtrueを返し、変換後の値をout引数に格納します。

変換に失敗した場合はfalseを返します。例外を発生させずに処理できるため、ユーザー入力や外部ファイル、APIレスポンスなど、不確実な文字列を扱う場面に向いています。

1-3. ParseとTryParseの違い

decimal.Parsedecimal.TryParseの大きな違いは、変換失敗時の動作です。

decimal.Parseは、変換に失敗すると例外を発生させます。

C#
string text = "abc";
decimal value = decimal.Parse(text); // FormatException

一方、decimal.TryParseは例外を発生させず、戻り値で成功・失敗を判定します。

C#
string text = "abc";

if (decimal.TryParse(text, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値に変換できません");
}

確実に数値であると分かっている文字列にはParse、変換できるか分からない文字列にはTryParseを使うのが基本です。

1-4. decimal型を使う場面

decimal型は、小数を正確に扱いたい場面でよく使われます。

代表的な用途は次のとおりです。

C#
decimal price = 1200.50m;
decimal taxRate = 0.10m;
decimal total = price * (1 + taxRate);

decimal型は、金額計算や会計処理のように、丸め誤差をできるだけ避けたい処理に向いています。

一方、科学技術計算や座標計算など、広い範囲の数値や高速な浮動小数点演算が必要な場合はdoubleが使われることもあります。

文字列から金額や数量を変換する場合は、decimal.Parsedecimal.TryParseを使うケースが多いです。

2. decimal.Parseで文字列をdecimalに変換する方法

decimal.Parseを使うと、数値形式の文字列を簡単にdecimal型へ変換できます。

2-1. 基本的な書き方

基本的な構文は次のとおりです。

C#
decimal value = decimal.Parse(文字列);

具体例を見てみましょう。

C#
string text = "123.45";
decimal value = decimal.Parse(text);

Console.WriteLine(value);

実行結果は次のようになります。

C#
123.45

decimal.Parseに渡す文字列は、現在のカルチャにおける数値形式として解釈されます。

日本語環境では通常、小数点は.、桁区切りは,として扱われます。

2-2. 変換できる文字列の例

次のような文字列は、一般的な環境ではdecimal.Parseで変換できます。

C#
decimal value1 = decimal.Parse("100");
decimal value2 = decimal.Parse("123.45");
decimal value3 = decimal.Parse("-50.25");
decimal value4 = decimal.Parse("1,234.56");

Console.WriteLine(value1);
Console.WriteLine(value2);
Console.WriteLine(value3);
Console.WriteLine(value4);

実行結果は次のようになります。

C#
100
123.45
-50.25
1234.56

decimal.Parseは、前後の空白も基本的には許容します。

C#
decimal value = decimal.Parse(" 123.45 ");

Console.WriteLine(value);

実行結果は次のようになります。

C#
123.45

ただし、空白が数値の途中に入っている場合や、数値として解釈できない文字が含まれている場合はエラーになります。

2-3. 小数点を含む文字列の変換

小数点を含む文字列もdecimal.Parseで変換できます。

C#
string text = "99.99";
decimal value = decimal.Parse(text);

Console.WriteLine(value);

実行結果は次のようになります。

C#
99.99

decimal型のリテラルを書く場合は末尾にmを付けますが、文字列から変換する場合は不要です。

C#
decimal value1 = 99.99m;              // decimalリテラル
decimal value2 = decimal.Parse("99.99"); // 文字列から変換

文字列内の小数点記号は、カルチャによって解釈が変わる点に注意が必要です。

たとえば、日本語環境や英語環境では"123.45"が一般的ですが、一部のヨーロッパ圏では"123,45"のようにカンマを小数点として扱う場合があります。

2-4. 負の数を含む文字列の変換

負の数を表す文字列も変換できます。

C#
string text = "-123.45";
decimal value = decimal.Parse(text);

Console.WriteLine(value);

実行結果は次のようになります。

C#
-123.45

負の数は、先頭にマイナス記号を付ける形式が一般的です。

C#
decimal value = decimal.Parse("-1000");

ただし、"▲1000""(1000)"のような会計表記は、標準のdecimal.Parseだけでは変換できない場合があります。

このような形式を扱う場合は、NumberStylesや事前の文字列加工が必要です。

3. decimal.Parseで発生する主なエラー

decimal.Parseは便利ですが、変換できない文字列を渡すと例外が発生します。

主な例外は次の3つです。

C#
FormatException
ArgumentNullException
OverflowException

それぞれの発生ケースを確認しておきましょう。

3-1. FormatExceptionが発生するケース

FormatExceptionは、文字列の形式が数値として正しくない場合に発生します。

C#
string text = "abc";
decimal value = decimal.Parse(text);

このコードでは、"abc"が数値として解釈できないためFormatExceptionが発生します。

ほかにも、次のような文字列はエラーになります。

C#
decimal.Parse("123abc");
decimal.Parse("円100");
decimal.Parse("");
decimal.Parse("1.2.3");

数値以外の文字が含まれている場合や、小数点が複数ある場合は変換できません。

3-2. ArgumentNullExceptionが発生するケース

ArgumentNullExceptionは、decimal.Parsenullを渡した場合に発生します。

C#
string text = null;
decimal value = decimal.Parse(text);

decimal.Parsenullを数値として解釈できないため、例外が発生します。

nullの可能性がある文字列を扱う場合は、事前にチェックするか、decimal.TryParseを使うと安全です。

C#
string text = null;

if (decimal.TryParse(text, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("変換できません");
}

TryParseであれば、nullを渡しても例外ではなくfalseで判定できます。

3-3. OverflowExceptionが発生するケース

OverflowExceptionは、文字列の数値がdecimal型で表現できる範囲を超えている場合に発生します。

C#
string text = "999999999999999999999999999999999999999999999";
decimal value = decimal.Parse(text);

decimal型には扱える数値の範囲があります。

その範囲を超える大きすぎる値や小さすぎる値を変換しようとすると、OverflowExceptionが発生します。

通常の金額や数量ではあまり発生しませんが、外部入力をそのまま変換する場合は注意が必要です。

3-4. エラーを防ぐための事前チェック

decimal.Parseでエラーを防ぐには、変換前に文字列をチェックします。

C#
string text = "123.45";

if (!string.IsNullOrWhiteSpace(text))
{
decimal value = decimal.Parse(text);
Console.WriteLine(value);
}
else
{
Console.WriteLine("値が入力されていません");
}

ただし、このチェックだけでは"abc"のような不正な文字列は防げません。

より安全に処理するなら、decimal.TryParseを使うのがおすすめです。

C#
string text = "abc";

if (decimal.TryParse(text, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値形式が正しくありません");
}

入力値が不確実な場合、Parseの前に細かくチェックするよりも、TryParseで変換できるか判定するほうが実装しやすくなります。

4. decimal.TryParseで安全に変換する方法

decimal.TryParseは、変換失敗時に例外を発生させず、戻り値で結果を判定できます。

そのため、ユーザー入力やCSVファイル、設定ファイル、外部APIの値などを扱うときに適しています。

4-1. 基本的な書き方

decimal.TryParseの基本形は次のとおりです。

C#
bool result = decimal.TryParse(文字列, out decimal 変換後の値);

具体例です。

C#
string text = "123.45";

bool success = decimal.TryParse(text, out decimal value);

Console.WriteLine(success);
Console.WriteLine(value);

実行結果は次のようになります。

C#
True
123.45

変換に成功すると、戻り値はtrueになり、valueに変換後の数値が入ります。

4-2. 変換成功時と失敗時の処理

変換に失敗した場合、TryParsefalseを返します。

C#
string text = "abc";

bool success = decimal.TryParse(text, out decimal value);

Console.WriteLine(success);
Console.WriteLine(value);

実行結果は次のようになります。

C#
False
0

変換に失敗した場合、out引数には通常0が入ります。

ただし、この0は入力された値が0だったという意味ではありません。変換に成功したかどうかは、必ず戻り値のtrueまたはfalseで判断します。

4-3. if文で分岐する実装例

実務では、if文と組み合わせて使うことが多いです。

C#
string input = "2500.75";

if (decimal.TryParse(input, out decimal amount))
{
Console.WriteLine($"金額は {amount} 円です");
}
else
{
Console.WriteLine("金額の形式が正しくありません");
}

変換できる場合だけ処理を続け、変換できない場合はエラーメッセージを表示できます。

次のように、早期リターンで処理を分ける書き方もよく使われます。

C#
static void PrintAmount(string input)
{
if (!decimal.TryParse(input, out decimal amount))
{
Console.WriteLine("数値を入力してください");
return;
}

Console.WriteLine($"入力された金額: {amount}");
}

このようにすると、不正な値の場合の処理を先に終わらせられるため、コードが読みやすくなります。

4-4. ユーザー入力を扱う場合にTryParseが向いている理由

ユーザー入力は、必ずしも正しい数値とは限りません。

たとえば、金額入力欄に次のような値が入力される可能性があります。

C#
"abc"
""
"100円"
"1,000"
" 500 "

decimal.Parseを使うと、不正な入力のたびに例外処理が必要になります。

C#
try
{
decimal value = decimal.Parse(input);
}
catch (FormatException)
{
Console.WriteLine("数値形式が正しくありません");
}

一方、decimal.TryParseなら、例外を使わずに自然な分岐で処理できます。

C#
if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine($"変換成功: {value}");
}
else
{
Console.WriteLine("数値形式が正しくありません");
}

ユーザー入力のように失敗が想定される処理では、TryParseを使うほうが安全で分かりやすいです。

5. ParseとTryParseの使い分け

decimal.Parsedecimal.TryParseは、どちらも文字列をdecimalに変換するためのメソッドです。

違いは、変換失敗を例外として扱うか、戻り値で扱うかです。

5-1. 確実に変換できる値ならParse

文字列が必ず正しい数値形式であると分かっている場合は、decimal.Parseを使っても問題ありません。

C#
string taxRateText = "0.10";
decimal taxRate = decimal.Parse(taxRateText);

たとえば、プログラム内で固定された文字列や、事前に検証済みの設定値などです。

C#
const string DefaultRate = "1.25";
decimal rate = decimal.Parse(DefaultRate);

このように、値の形式を開発者が完全に制御できる場合はParseでも十分です。

5-2. 入力値が不確実ならTryParse

ユーザーが入力した値、外部ファイルから読み込んだ値、APIから取得した値などは、形式が保証されないことがあります。

そのような場合はdecimal.TryParseを使います。

C#
string input = Console.ReadLine();

if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine($"入力値: {value}");
}
else
{
Console.WriteLine("数値を入力してください");
}

不正な値が入ってくる可能性がある場面では、TryParseを使うことで例外による処理中断を防げます。

5-3. 例外処理と戻り値による判定の違い

Parseは、失敗時に例外を発生させます。

C#
try
{
decimal value = decimal.Parse(input);
Console.WriteLine(value);
}
catch (FormatException)
{
Console.WriteLine("形式が正しくありません");
}

一方、TryParseは戻り値で判定します。

C#
if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("形式が正しくありません");
}

例外処理は、本来は予期しない異常な状態を扱うための仕組みです。

入力ミスのように日常的に起こり得る失敗は、TryParseで通常の分岐として扱うほうが適しています。

5-4. 実務でおすすめの使い分け

実務では、次のように使い分けると分かりやすいです。

C#
// 開発者が管理している固定値
decimal rate = decimal.Parse("1.08");

// ユーザー入力
if (decimal.TryParse(userInput, out decimal amount))
{
// 正常処理
}
else
{
// エラー処理
}

基本方針としては、外部から入ってくる値にはTryParseを使うのがおすすめです。

特に、画面入力、CSV、Excel、JSON、設定ファイル、データベースから取得した文字列などは、想定外の値が含まれる可能性があります。

そのため、実務ではdecimal.Parseよりもdecimal.TryParseを使う場面のほうが多くなります。

6. カンマ・通貨記号・空白を含む文字列の変換

文字列には、単純な数値だけでなく、カンマ区切りや通貨記号、空白が含まれている場合があります。

C#
"1,234.56"
"¥1,234"
" 123.45 "

このような文字列を変換するには、NumberStylesCultureInfoを適切に指定します。

6-1. カンマ区切りの数値を変換する方法

カンマ区切りの数値は、一般的な日本語環境や英語環境ではそのまま変換できることがあります。

C#
string text = "1,234.56";
decimal value = decimal.Parse(text);

Console.WriteLine(value);

実行結果は次のようになります。

C#
1234.56

decimal.TryParseでも同様です。

C#
string text = "1,234.56";

if (decimal.TryParse(text, out decimal value))
{
Console.WriteLine(value);
}

ただし、カンマが桁区切りとして解釈されるかどうかはカルチャに依存します。

環境差を避けるには、CultureInfoを明示するのが安全です。

6-2. NumberStylesを指定する方法

NumberStylesを指定すると、どのような形式の文字列を許可するかを細かく制御できます。

C#
using System.Globalization;

string text = "1,234.56";

decimal value = decimal.Parse(
text,
NumberStyles.Number,
CultureInfo.InvariantCulture
);

Console.WriteLine(value);

NumberStyles.Numberを指定すると、前後の空白、符号、小数点、桁区切りなどを許可できます。

TryParseでも同じように指定できます。

C#
using System.Globalization;

string text = "1,234.56";

bool success = decimal.TryParse(
text,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal value
);

if (success)
{
Console.WriteLine(value);
}

形式を明示することで、実行環境による違いを減らせます。

6-3. 通貨記号を含む文字列の変換

"¥1,234""$1,234.56"のように通貨記号を含む文字列を変換する場合は、NumberStyles.Currencyを指定します。

C#
using System.Globalization;

string text = "¥1,234";

decimal value = decimal.Parse(
text,
NumberStyles.Currency,
CultureInfo.GetCultureInfo("ja-JP")
);

Console.WriteLine(value);

実行結果は次のようになります。

C#
1234

TryParseで安全に処理する場合は次のように書きます。

C#
using System.Globalization;

string text = "¥1,234";

if (decimal.TryParse(
text,
NumberStyles.Currency,
CultureInfo.GetCultureInfo("ja-JP"),
out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("通貨形式として変換できません");
}

通貨記号はカルチャによって異なります。

日本円ならja-JP、米ドルならen-USのように、対象の形式に合わせてCultureInfoを指定しましょう。

6-4. 前後の空白をTrimで取り除く方法

decimal.Parsedecimal.TryParseは、前後の空白を許容する場合があります。

しかし、入力値を扱うときは、事前にTrimで余分な空白を取り除くと処理が分かりやすくなります。

C#
string input = " 123.45 ";
string trimmed = input.Trim();

decimal value = decimal.Parse(trimmed);

Console.WriteLine(value);

実行結果は次のようになります。

C#
123.45

TryParseと組み合わせる場合は次のように書けます。

C#
string input = " 123.45 ";
string trimmed = input?.Trim();

if (decimal.TryParse(trimmed, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("変換できません");
}

input?.Trim()のように書くと、inputnullの場合でも例外を防げます。

7. 小数点やカルチャによる変換エラー対策

decimal.Parsedecimal.TryParseで意外と多いのが、カルチャによる変換エラーです。

カルチャとは、言語や地域ごとの数値、日付、通貨などの表記ルールのことです。

7-1. 日本語環境と英語環境での違い

日本語環境や英語環境では、一般的に次のような表記が使われます。

C#
"1,234.56"

この場合、,は桁区切り、.は小数点です。

一方、一部のヨーロッパ圏では次のような表記が使われることがあります。

C#
"1.234,56"

この場合、.が桁区切り、,が小数点として扱われます。

そのため、同じ文字列でも、実行環境のカルチャによって変換結果が変わったり、変換に失敗したりする可能性があります。

7-2. CultureInfoを指定して変換する方法

環境差を防ぐには、CultureInfoを明示して変換します。

C#
using System.Globalization;

string text = "1,234.56";

decimal value = decimal.Parse(
text,
NumberStyles.Number,
CultureInfo.GetCultureInfo("en-US")
);

Console.WriteLine(value);

日本語環境の形式として扱いたい場合は、ja-JPを指定できます。

C#
using System.Globalization;

string text = "1,234.56";

decimal value = decimal.Parse(
text,
NumberStyles.Number,
CultureInfo.GetCultureInfo("ja-JP")
);

Console.WriteLine(value);

TryParseでも同様です。

C#
using System.Globalization;

string text = "1,234.56";

if (decimal.TryParse(
text,
NumberStyles.Number,
CultureInfo.GetCultureInfo("ja-JP"),
out decimal value))
{
Console.WriteLine(value);
}

実務では、アプリケーションで受け付ける数値形式を決め、その形式に合わせたCultureInfoを指定するのが安全です。

7-3. 小数点と桁区切り記号の違いに注意する

小数点と桁区切り記号は、カルチャによって異なります。

たとえば、次の文字列を考えます。

C#
"1,234"

日本語環境や英語環境では、これは1234として解釈されることが多いです。

しかし、カンマを小数点として扱うカルチャでは、1.234として解釈される可能性があります。

このような違いを避けるには、入力形式を明確に決めることが大切です。

C#
using System.Globalization;

string text = "1,234";

decimal value = decimal.Parse(
text,
NumberStyles.Number,
CultureInfo.GetCultureInfo("ja-JP")
);

数値の受け渡しをシステム間で行う場合は、特定のローカル形式ではなく、共通形式を使うことも検討しましょう。

7-4. InvariantCultureを使うケース

InvariantCultureは、特定の国や地域に依存しないカルチャです。

ログ、設定ファイル、CSV、JSON、API連携など、環境に左右されない形式で数値を扱いたい場合に使われます。

C#
using System.Globalization;

string text = "1234.56";

decimal value = decimal.Parse(
text,
NumberStyles.Number,
CultureInfo.InvariantCulture
);

Console.WriteLine(value);

InvariantCultureでは、一般的に.を小数点として扱います。

C#
using System.Globalization;

decimal price = 1234.56m;

string text = price.ToString(CultureInfo.InvariantCulture);
decimal value = decimal.Parse(text, CultureInfo.InvariantCulture);

Console.WriteLine(value);

文字列へ変換するときと、文字列から戻すときの両方で同じカルチャを指定すると、環境差による不具合を防ぎやすくなります。

8. null・空文字・不正な文字列を扱う実装例

実務では、null、空文字、数値以外の文字を含む文字列を扱うことがよくあります。

C#
null
""
"abc"
"100円"

このような値を安全に処理するには、TryParseを中心に実装するのがおすすめです。

8-1. nullの場合の対策

decimal.Parsenullを渡すと例外が発生します。

C#
string input = null;
decimal value = decimal.Parse(input); // ArgumentNullException

nullの可能性がある場合は、TryParseを使うと安全です。

C#
string input = null;

if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("値がありません");
}

また、事前にstring.IsNullOrWhiteSpaceでチェックする方法もあります。

C#
string input = null;

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("入力値が空です");
}
else
{
decimal value = decimal.Parse(input);
Console.WriteLine(value);
}

ただし、この方法では数値形式の正しさまでは判定できないため、最終的にはTryParseと組み合わせるのが安全です。

8-2. 空文字の場合の対策

空文字をdecimal.Parseで変換しようとすると、FormatExceptionが発生します。

C#
string input = "";
decimal value = decimal.Parse(input); // FormatException

空文字を扱う場合も、TryParseを使います。

C#
string input = "";

if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値が入力されていません");
}

空文字や空白だけの文字列を明確に分けたい場合は、先にチェックします。

C#
string input = " ";

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("入力してください");
}
else if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値形式が正しくありません");
}

このようにすると、「未入力」と「形式エラー」を分けて扱えます。

8-3. 数値以外の文字が含まれる場合の対策

数値以外の文字が含まれる場合、通常は変換に失敗します。

C#
string input = "100円";

if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値以外の文字が含まれています");
}

実行結果は次のようになります。

C#
数値以外の文字が含まれています

ただし、通貨記号として扱いたい場合は、NumberStyles.CurrencyCultureInfoを指定します。

C#
using System.Globalization;

string input = "¥100";

if (decimal.TryParse(
input,
NumberStyles.Currency,
CultureInfo.GetCultureInfo("ja-JP"),
out decimal value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("通貨形式として正しくありません");
}

単位や文字を許可するのか、数値だけを許可するのかは、仕様として決めておくことが重要です。

8-4. 実務向けの共通変換メソッド例

複数の場所でdecimal変換を行う場合は、共通メソッドにまとめると便利です。

C#
using System.Globalization;

public static class DecimalHelper
{
public static bool TryConvertToDecimal(string input, out decimal value)
{
value = 0m;

if (string.IsNullOrWhiteSpace(input))
{
return false;
}

return decimal.TryParse(
input.Trim(),
NumberStyles.Number,
CultureInfo.InvariantCulture,
out value
);
}
}

使い方は次のとおりです。

C#
string input = "1234.56";

if (DecimalHelper.TryConvertToDecimal(input, out decimal amount))
{
Console.WriteLine($"変換成功: {amount}");
}
else
{
Console.WriteLine("変換できません");
}

エラー理由も返したい場合は、戻り値を工夫します。

C#
using System.Globalization;

public static class DecimalHelper
{
public static decimal? ConvertToNullableDecimal(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
return null;
}

if (decimal.TryParse(
input.Trim(),
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal value))
{
return value;
}

return null;
}
}

decimal?を返すことで、変換できなかった場合にnullとして扱えます。

C#
decimal? value = DecimalHelper.ConvertToNullableDecimal("123.45");

if (value.HasValue)
{
Console.WriteLine(value.Value);
}
else
{
Console.WriteLine("変換できません");
}

9. decimal変換時によくある疑問

ここでは、C#で文字列をdecimalに変換するときによくある疑問を整理します。

9-1. decimal.ParseとConvert.ToDecimalの違い

decimal.ParseConvert.ToDecimalは、どちらも文字列をdecimalに変換できます。

C#
string text = "123.45";

decimal value1 = decimal.Parse(text);
decimal value2 = Convert.ToDecimal(text);

大きな違いのひとつは、nullを渡した場合の動作です。

C#
string text = null;

decimal value = Convert.ToDecimal(text);

Console.WriteLine(value);

Convert.ToDecimal(string)nullを渡すと、結果は0になります。

一方、decimal.Parse(null)ArgumentNullExceptionになります。

C#
string text = null;

decimal value = decimal.Parse(text); // ArgumentNullException

null0として扱いたいのか、エラーとして扱いたいのかによって使い分けが必要です。

ただし、不正な文字列を渡した場合は、Convert.ToDecimalでも例外が発生します。

C#
decimal value = Convert.ToDecimal("abc"); // FormatException

入力値が不確実な場合は、Convert.ToDecimalよりもdecimal.TryParseを使うほうが安全です。

9-2. decimalとdoubleの違い

decimaldoubleは、どちらも小数を扱える型です。

ただし、用途が異なります。

decimalは、金額や会計処理など、10進数としての正確さを重視する場面に向いています。

C#
decimal price = 0.1m;
decimal total = price + price + price;

Console.WriteLine(total);

一方、doubleは、科学技術計算や座標計算など、広い範囲の数値や高速な計算が必要な場面で使われます。

C#
double x = 0.1;
double y = x + x + x;

Console.WriteLine(y);

金額を扱う場合は、基本的にdecimalを選ぶのが一般的です。

文字列から金額を変換する場合も、double.Parseではなくdecimal.Parsedecimal.TryParseを使うとよいでしょう。

9-3. 四捨五入や桁数指定は変換後に行うべきか

文字列をdecimalに変換するとき、基本的には変換後に四捨五入や桁数指定を行います。

C#
string text = "123.4567";

decimal value = decimal.Parse(text);
decimal rounded = Math.Round(value, 2);

Console.WriteLine(rounded);

実行結果は次のようになります。

C#
123.46

表示だけ桁数を指定したい場合は、ToStringの書式指定を使います。

C#
decimal value = 123.4567m;

Console.WriteLine(value.ToString("F2"));

実行結果は次のようになります。

C#
123.46

内部的な数値を丸めたいのか、表示だけ整えたいのかを分けて考えることが大切です。

9-4. decimal.Parseで「1,234.56」は変換できるか

多くの日本語環境や英語環境では、"1,234.56"decimal.Parseで変換できます。

C#
string text = "1,234.56";
decimal value = decimal.Parse(text);

Console.WriteLine(value);

実行結果は次のようになります。

C#
1234.56

ただし、カルチャによっては解釈が変わる可能性があります。

確実に1,234.56を英語圏や共通形式として扱いたい場合は、CultureInfo.InvariantCultureを指定します。

C#
using System.Globalization;

string text = "1,234.56";

decimal value = decimal.Parse(
text,
NumberStyles.Number,
CultureInfo.InvariantCulture
);

Console.WriteLine(value);

環境差を避けたい場合は、decimal.Parsedecimal.TryParseCultureInfoを明示するのが安全です。

10. C#で文字列をdecimalに変換する際のベストプラクティス

最後に、C#で文字列をdecimalに変換する際のベストプラクティスを整理します。

10-1. 基本はTryParseで安全に処理する

実務では、基本的にdecimal.TryParseを使うのがおすすめです。

C#
if (decimal.TryParse(input, out decimal value))
{
// 変換成功時の処理
}
else
{
// 変換失敗時の処理
}

TryParseを使えば、変換に失敗しても例外で処理が中断されません。

ユーザー入力、CSV、JSON、設定ファイル、外部APIなど、不確実な値を扱う場合に適しています。

10-2. 入力値の形式を事前に決めておく

数値の入力形式は、事前に決めておくことが重要です。

たとえば、次のようなルールを明確にします。

C#
小数点は . を使う
桁区切りのカンマを許可する
通貨記号は許可しない
前後の空白は無視する

仕様が曖昧なままだと、変換できる値とできない値の基準が分かりにくくなります。

入力フォームであれば、プレースホルダーやエラーメッセージで形式を案内すると親切です。

C#
: 1234.56

受け付ける形式を決めたうえで、NumberStylesCultureInfoを合わせて指定しましょう。

10-3. CultureInfoを明示して環境差を防ぐ

decimal.Parsedecimal.TryParseは、現在のカルチャに影響されます。

そのため、実行環境によって変換結果が変わる可能性があります。

環境差を防ぐには、CultureInfoを明示します。

C#
using System.Globalization;

bool success = decimal.TryParse(
input,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal value
);

日本向けの入力として扱うならja-JPを指定します。

C#
using System.Globalization;

bool success = decimal.TryParse(
input,
NumberStyles.Number,
CultureInfo.GetCultureInfo("ja-JP"),
out decimal value
);

システム間連携や設定ファイルではInvariantCulture、ユーザー向けのローカル入力では対象地域のCultureInfoを使うとよいでしょう。

10-4. エラー時の戻り値やメッセージを設計する

変換に失敗したとき、単に「エラー」とするのではなく、原因に応じたメッセージを設計すると使いやすくなります。

C#
string input = "";

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("数値を入力してください");
}
else if (!decimal.TryParse(input, out decimal value))
{
Console.WriteLine("数値形式が正しくありません");
}
else
{
Console.WriteLine($"入力値: {value}");
}

未入力、形式エラー、範囲外エラーなどを分けたい場合は、共通メソッドにまとめると管理しやすくなります。

C#
using System.Globalization;

public static bool TryParseAmount(string input, out decimal amount, out string errorMessage)
{
amount = 0m;
errorMessage = "";

if (string.IsNullOrWhiteSpace(input))
{
errorMessage = "金額を入力してください";
return false;
}

if (!decimal.TryParse(
input.Trim(),
NumberStyles.Number,
CultureInfo.GetCultureInfo("ja-JP"),
out amount))
{
errorMessage = "金額は数値で入力してください";
return false;
}

if (amount < 0)
{
errorMessage = "金額は0以上で入力してください";
return false;
}

return true;
}

使い方は次のとおりです。

C#
string input = "1234";

if (TryParseAmount(input, out decimal amount, out string error))
{
Console.WriteLine($"金額: {amount}");
}
else
{
Console.WriteLine(error);
}

このように、変換処理とエラー処理をまとめておくと、画面やAPIで再利用しやすくなります。

まとめ

C#で文字列をdecimalに変換するには、decimal.Parseまたはdecimal.TryParseを使います。

decimal.Parseは、文字列が確実に数値形式である場合に便利です。

C#
decimal value = decimal.Parse("123.45");

ただし、変換できない文字列を渡すとFormatExceptionArgumentNullExceptionOverflowExceptionなどの例外が発生します。

一方、decimal.TryParseは、変換に成功したかどうかを戻り値で判定できます。

C#
if (decimal.TryParse("123.45", out decimal value))
{
Console.WriteLine(value);
}

ユーザー入力や外部データのように、値が正しいとは限らない場合はTryParseを使うのが安全です。

また、カンマ区切り、通貨記号、小数点、カルチャの違いにも注意が必要です。

C#
using System.Globalization;

decimal.TryParse(
input,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal value
);

実務では、次の方針で実装すると安定します。

C#
外部入力はdecimal.TryParseで安全に変換する
数値形式を事前に決める
NumberStylesで許可する形式を明示する
CultureInfoを指定して環境差を防ぐ
変換失敗時のメッセージを設計する

decimal.Parsedecimal.TryParseの違いを理解し、入力値の性質に合わせて使い分けることで、C#での文字列からdecimalへの変換を安全に実装できます。