C#の数値変換を完全解説|Parse・TryParse・Convertの違いとエラーを防ぐ安全な使い分け
はじめに
C#で開発していると、文字列を数値に変換する場面は非常に多くあります。たとえば、画面のテキストボックスに入力された値をintに変換する、CSVから読み込んだ金額をdecimalに変換する、APIから返ってきた数値文字列をdoubleに変換する、といったケースです。
しかし、C#の数値変換にはParse、TryParse、Convert、キャストなど複数の方法があり、使い分けを誤るとFormatExceptionやOverflowExceptionなどの例外が発生します。
この記事では、C#の数値変換について、基本から実務での安全な使い分けまで解説します。特に、Parse、TryParse、Convertの違いを理解し、エラーを防ぐ書き方を身につけることを目的としています。
1. C#の数値変換でよくある悩みとこの記事で解決できること
1-1. 文字列をint・double・decimalに変換したい
C#では、文字列を数値に変換する代表的な方法として、各数値型に用意されているParseやTryParseを使用します。Microsoftの公式ドキュメントでも、数値型には文字列を数値型へ変換するためのParseとTryParseが用意されていると説明されています。
C#string text = "123";
int number = int.Parse(text);
double doubleValue = double.Parse("123.45");
decimal decimalValue = decimal.Parse("123.45");
このように、文字列が正しい数値形式であれば簡単に変換できます。
ただし、実務では常に正しい値が入っているとは限りません。空文字、null、カンマ付きの数値、不正な文字列、範囲外の値などを考慮する必要があります。
1-2. Parse・TryParse・Convertの違いが分からない
C#の数値変換で混乱しやすいのが、Parse、TryParse、Convertの違いです。
簡単にいうと、次のように使い分けます。
| 方法 | 特徴 | 主な用途 |
|---|---|---|
Parse | 変換できないと例外が発生する | 値が必ず正しいと分かっている場合 |
TryParse | 成功・失敗をboolで判定できる | ユーザー入力や外部データの変換 |
Convert | nullの扱いなどがParseと異なる | 汎用的な型変換 |
実務では、エラーを避けるためにTryParseを使う場面が最も多くなります。
1-3. FormatExceptionやOverflowExceptionを防ぎたい
FormatExceptionは、文字列の形式が数値として正しくない場合に発生します。
C#int value = int.Parse("abc"); // FormatException
OverflowExceptionは、変換先の型に収まらない値を変換しようとした場合に発生します。
C#int value = int.Parse("999999999999"); // OverflowException
これらの例外は、TryParseを使うことで事前に防げます。
C#if (int.TryParse("abc", out int value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値に変換できません。");
}
1-4. null・空文字・不正な入力を安全に処理したい
ユーザー入力や外部ファイルの値には、null、空文字、不正な文字列が含まれることがあります。
C#string? input = null;
このような値に対してParseを使うと例外が発生する可能性があります。一方、TryParseであれば例外を出さずに失敗として処理できます。
C#string? input = null;
if (int.TryParse(input, out int result))
{
Console.WriteLine(result);
}
else
{
Console.WriteLine("入力値が不正です。");
}
安全な数値変換を行うには、「変換できない可能性がある値にはTryParseを使う」と覚えておくとよいでしょう。
1-5. 実務でどの変換方法を選ぶべきか判断したい
実務での基本方針は次の通りです。
| 状況 | 推奨する方法 |
|---|---|
| ユーザー入力を変換する | TryParse |
| CSVやAPIなど外部データを変換する | TryParse |
| 固定値や内部的に保証された文字列を変換する | Parse |
nullを0として扱いたい | Convert |
| 数値型同士を変換する | キャストまたはConvert |
特に、画面入力、ファイル読み込み、APIレスポンスなど、外部から入ってくる値は信用せず、TryParseで安全に判定するのが基本です。
2. C#の数値変換の基本
2-1. 数値変換とは何か
C#の数値変換とは、ある値を別の数値型に変える処理のことです。
たとえば、次のような変換があります。
C#string text = "100";
int number = int.Parse(text);
これは、文字列"100"を整数型の100に変換しています。
また、数値型同士の変換も数値変換に含まれます。
C#int intValue = 100;
double doubleValue = intValue;
この例では、int型の値をdouble型に変換しています。
2-2. 文字列から数値への変換
文字列から数値への変換では、主に次のメソッドを使います。
C#int.Parse("123");
int.TryParse("123", out int result);
Convert.ToInt32("123");
それぞれ同じように見えますが、エラー時の動作やnullの扱いが異なります。
C#string text = "123";
int a = int.Parse(text);
if (int.TryParse(text, out int b))
{
Console.WriteLine(b);
}
int c = Convert.ToInt32(text);
値が確実に正しいならParseでも問題ありませんが、入力値が不確実な場合はTryParseを使うのが安全です。
2-3. 数値型同士の変換
C#では、intからdoubleのように安全に変換できる場合は、自動的に変換できます。
C#int intValue = 100;
double doubleValue = intValue;
一方、doubleからintのように小数点以下が失われる可能性がある変換では、明示的なキャストが必要です。
C#double doubleValue = 123.45;
int intValue = (int)doubleValue;
Console.WriteLine(intValue); // 123
C#では数値型同士に暗黙的変換と明示的変換があり、明示的変換にはキャスト式を使用します。
2-4. 暗黙的変換と明示的変換の違い
暗黙的変換は、データの損失が起きにくい変換で、C#が自動的に行います。
C#int intValue = 10;
long longValue = intValue;
double doubleValue = intValue;
intからlong、doubleへの変換は、通常値を表現できる範囲が広がるため、暗黙的に変換できます。
一方、明示的変換は、データの損失や範囲外の可能性があるため、開発者がキャストを指定する必要があります。
C#double doubleValue = 10.9;
int intValue = (int)doubleValue;
Console.WriteLine(intValue); // 10
この場合、小数点以下は切り捨てられます。
2-5. 型変換で注意すべき桁あふれと精度落ち
数値変換で注意すべきポイントは、桁あふれと精度落ちです。
桁あふれは、変換先の型で表現できる範囲を超えた場合に発生します。
C#long longValue = 3000000000;
int intValue = (int)longValue;
このような変換では、期待しない値になる可能性があります。範囲を厳密にチェックしたい場合は、checkedを使います。
C#long longValue = 3000000000;
try
{
int intValue = checked((int)longValue);
}
catch (OverflowException)
{
Console.WriteLine("intの範囲を超えています。");
}
精度落ちは、decimalからdouble、doubleからfloatなど、表現精度が異なる型へ変換するときに発生することがあります。
金額計算ではdecimal、一般的な小数計算ではdoubleを使うなど、用途に合わせて型を選ぶことが重要です。
3. Parseを使った数値変換
3-1. Parseの基本的な使い方
Parseは、文字列を指定した数値型に変換するメソッドです。
C#string text = "100";
int value = int.Parse(text);
Console.WriteLine(value); // 100
Parseは、文字列が正しい数値形式であることを前提にしています。そのため、不正な文字列を渡すと例外が発生します。
C#int value = int.Parse("abc"); // 例外
3-2. int.Parseで文字列を整数に変換する
int.Parseは、文字列をint型に変換します。
C#string text = "123";
int number = int.Parse(text);
Console.WriteLine(number + 10); // 133
マイナスの値も変換できます。
C#int value = int.Parse("-123");
Console.WriteLine(value); // -123
前後の空白は基本的に許容されます。
C#int value = int.Parse(" 123 ");
Console.WriteLine(value); // 123
ただし、カンマ区切りの文字列は、そのままでは変換できない場合があります。
C#int value = int.Parse("1,000"); // 環境や指定方法によっては例外
カンマを含む数値を扱う場合は、NumberStylesとCultureInfoを指定します。
C#using System.Globalization;
string text = "1,000";
int value = int.Parse(
text,
NumberStyles.AllowThousands,
CultureInfo.InvariantCulture
);
Console.WriteLine(value); // 1000
3-3. double.Parse・decimal.Parseで小数を変換する
小数を扱う場合は、double.Parseやdecimal.Parseを使います。
C#double doubleValue = double.Parse("123.45");
decimal decimalValue = decimal.Parse("123.45");
Console.WriteLine(doubleValue);
Console.WriteLine(decimalValue);
doubleは科学計算や一般的な小数計算に向いています。一方、decimalは10進数の精度を重視するため、金額計算に向いています。
C#decimal price = decimal.Parse("1980.50");
Console.WriteLine(price);
CSVやAPIなど、数値の小数点が.で固定されているデータを扱う場合は、CultureInfo.InvariantCultureを指定すると環境差を避けやすくなります。
C#using System.Globalization;
string text = "123.45";
decimal value = decimal.Parse(
text,
CultureInfo.InvariantCulture
);
数値の解析では、カルチャ固有の小数点記号や桁区切り記号が関係します。NumberFormatInfoには、小数点記号や桁区切り記号など、数値の書式と解析に関する情報が含まれています。
3-4. Parseで発生しやすい例外
Parseで発生しやすい例外は、主に次の3つです。
| 例外 | 原因 |
|---|---|
FormatException | 数値として解釈できない文字列 |
OverflowException | 変換先の型の範囲を超えている |
ArgumentNullException | nullを渡した場合 |
例を見てみましょう。
C#int.Parse("abc"); // FormatException
int.Parse("999999999999"); // OverflowException
int.Parse(null); // ArgumentNullException
Parseを使う場合は、これらの例外が発生する可能性を考慮する必要があります。
C#try
{
int value = int.Parse("abc");
}
catch (FormatException)
{
Console.WriteLine("数値形式が正しくありません。");
}
catch (OverflowException)
{
Console.WriteLine("値が範囲外です。");
}
ただし、ユーザー入力のように失敗が想定される場面で毎回例外処理を書くより、TryParseを使う方がシンプルです。
3-5. Parseを使うべき場面と避けるべき場面
Parseを使うべき場面は、値が必ず正しいと保証できる場合です。
C#string fixedValue = "100";
int value = int.Parse(fixedValue);
たとえば、プログラム内部で固定している文字列、テストデータ、仕様上必ず数値形式になる値などです。
一方、次のような場面ではParseを避けるべきです。
| 避けるべき場面 | 理由 |
|---|---|
| テキストボックスの入力値 | ユーザーが不正な値を入力する可能性がある |
| CSVファイルの読み込み | 欠損値や不正データが含まれる可能性がある |
| APIレスポンス | 想定外の値や空文字が返る可能性がある |
| データベースの文字列項目 | 過去データに不整合がある可能性がある |
失敗が想定される変換では、基本的にTryParseを使いましょう。
4. TryParseを使った安全な数値変換
4-1. TryParseの基本的な使い方
TryParseは、文字列を数値に変換できるかどうかを判定し、成功した場合だけ変換結果を取得できるメソッドです。
C#string text = "123";
if (int.TryParse(text, out int value))
{
Console.WriteLine($"変換成功: {value}");
}
else
{
Console.WriteLine("変換失敗");
}
TryParseの戻り値はboolです。
| 戻り値 | 意味 |
|---|---|
true | 変換成功 |
false | 変換失敗 |
変換に成功すると、out引数に変換後の値が入ります。失敗した場合でも例外は発生しません。
4-2. TryParseがエラー対策に向いている理由
TryParseがエラー対策に向いている理由は、変換できない値を例外ではなく通常の分岐として扱えるからです。
C#string input = "abc";
if (!int.TryParse(input, out int value))
{
Console.WriteLine("整数を入力してください。");
return;
}
Console.WriteLine(value);
この書き方であれば、ユーザーが不正な値を入力してもアプリケーションが例外で停止することを防げます。
特に、次のような値を扱うときに有効です。
| 入力値 | TryParseの結果 |
|---|---|
"123" | true |
"abc" | false |
"" | false |
null | false |
"999999999999" | false |
4-3. int.TryParseで入力値を安全に判定する
整数入力を安全に処理する例です。
C#Console.Write("年齢を入力してください: ");
string? input = Console.ReadLine();
if (int.TryParse(input, out int age))
{
Console.WriteLine($"年齢は{age}歳です。");
}
else
{
Console.WriteLine("年齢は整数で入力してください。");
}
さらに、範囲チェックも組み合わせると実務的です。
C#string? input = Console.ReadLine();
if (!int.TryParse(input, out int age))
{
Console.WriteLine("整数で入力してください。");
return;
}
if (age < 0 || age > 120)
{
Console.WriteLine("年齢は0〜120の範囲で入力してください。");
return;
}
Console.WriteLine($"入力された年齢: {age}");
TryParseは形式チェック、範囲チェックは別途ifで行う、と分けて考えると分かりやすくなります。
4-4. double.TryParse・decimal.TryParseの使い分け
小数を変換する場合は、用途に応じてdouble.TryParseとdecimal.TryParseを使い分けます。
C#double.TryParse("123.45", out double doubleValue);
decimal.TryParse("123.45", out decimal decimalValue);
一般的な使い分けは次の通りです。
| 型 | 向いている用途 |
|---|---|
double | 科学計算、測定値、座標、割合 |
decimal | 金額、税率、請求額、会計処理 |
float | メモリ使用量を抑えたい大量データ、ゲーム、グラフィックス |
金額を扱う場合は、基本的にdecimalを選びます。
C#string input = "1980.50";
if (decimal.TryParse(input, out decimal price))
{
Console.WriteLine($"価格: {price}円");
}
else
{
Console.WriteLine("価格の形式が正しくありません。");
}
CSVやAPIでは、カルチャ差による誤変換を避けるため、CultureInfo.InvariantCultureを指定するのがおすすめです。
C#using System.Globalization;
string input = "123.45";
bool success = decimal.TryParse(
input,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal value
);
if (success)
{
Console.WriteLine(value);
}
Decimal.TryParseには、スタイルやカルチャを指定して変換するオーバーロードが用意されています。
4-5. ユーザー入力やCSV読み込みでTryParseを使う例
CSVから金額を読み込む例です。
C#using System.Globalization;
string csvValue = "1234.56";
if (decimal.TryParse(
csvValue,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal amount))
{
Console.WriteLine($"金額: {amount}");
}
else
{
Console.WriteLine("CSVの金額データが不正です。");
}
複数行のCSVを処理する場合は、不正な行をスキップしたり、エラーログに記録したりします。
C#using System.Globalization;
string[] values = { "100.50", "abc", "200.75", "" };
foreach (string value in values)
{
if (decimal.TryParse(
value,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal amount))
{
Console.WriteLine($"変換成功: {amount}");
}
else
{
Console.WriteLine($"変換失敗: {value}");
}
}
外部データを扱うときは、失敗する前提でコードを書くことが重要です。
5. Convertを使った数値変換
5-1. Convert.ToInt32の基本的な使い方
Convert.ToInt32は、値をint型に変換するメソッドです。
C#string text = "123";
int value = Convert.ToInt32(text);
Console.WriteLine(value); // 123
文字列だけでなく、doubleやdecimalなどの値も変換できます。
C#double doubleValue = 123.45;
int intValue = Convert.ToInt32(doubleValue);
Console.WriteLine(intValue);
ただし、Convert.ToInt32は小数を整数に変換するときに丸め処理を行います。キャストとは挙動が違うため注意が必要です。
5-2. ConvertとParseの違い
ConvertとParseの大きな違いは、nullの扱いです。
C#string? text = null;
int value = Convert.ToInt32(text);
Console.WriteLine(value); // 0
Convert.ToInt32(null)は0を返します。
一方、int.Parse(null)は例外になります。
C#string? text = null;
int value = int.Parse(text); // ArgumentNullException
この違いは非常に重要です。
nullを0として扱いたい場合はConvertが便利ですが、nullを不正値として検出したい場合はTryParseなどで明示的に判定する方が安全です。
5-3. nullを変換した場合の挙動
Convertでは、nullを変換すると型に応じた既定値になります。
C#string? text = null;
int intValue = Convert.ToInt32(text);
double doubleValue = Convert.ToDouble(text);
decimal decimalValue = Convert.ToDecimal(text);
Console.WriteLine(intValue); // 0
Console.WriteLine(doubleValue); // 0
Console.WriteLine(decimalValue); // 0
この挙動は便利な反面、入力漏れを見逃す原因にもなります。
たとえば、金額が未入力なのに0円として処理されてしまうと、業務上の不具合につながる可能性があります。
C#string? priceText = null;
decimal price = Convert.ToDecimal(priceText);
// 未入力なのに0として処理される
Console.WriteLine(price); // 0
未入力をエラーとして扱いたい場合は、次のように明示的にチェックします。
C#string? priceText = null;
if (string.IsNullOrWhiteSpace(priceText))
{
Console.WriteLine("金額を入力してください。");
return;
}
decimal price = Convert.ToDecimal(priceText);
5-4. Convertで発生する例外
Convertでも、不正な文字列や範囲外の値では例外が発生します。
C#Convert.ToInt32("abc"); // FormatException
Convert.ToInt32("999999999999"); // OverflowException
nullは0になりますが、空文字は変換できません。
C#Convert.ToInt32(""); // FormatException
つまり、Convertはnullには強いものの、不正文字列や空文字まで安全に処理できるわけではありません。
安全性を重視する場合は、やはりTryParseを使うべきです。
5-5. Convertを使うべき場面と注意点
Convertを使うべき場面は、値の型が一定でない場合や、nullを既定値として扱いたい場合です。
C#object value = "123";
int number = Convert.ToInt32(value);
ただし、次の点には注意が必要です。
| 注意点 | 内容 |
|---|---|
nullが0になる | 未入力を見逃す可能性がある |
| 不正文字列では例外が出る | "abc"や""は変換できない |
| 小数から整数では丸められる | キャストとは結果が異なる |
| 範囲外では例外が出る | intの範囲を超える値は変換できない |
Convertは便利ですが、入力チェックを省略できるものではありません。
6. Parse・TryParse・Convertの違いと使い分け
6-1. 3つの変換方法の比較表
Parse、TryParse、Convertの違いをまとめると、次のようになります。
| 項目 | Parse | TryParse | Convert |
|---|---|---|---|
| 変換成功時 | 変換後の値を返す | trueを返し、outに値を入れる | 変換後の値を返す |
| 変換失敗時 | 例外 | false | 例外 |
nullの扱い | 例外 | false | 数値型では0 |
| 空文字の扱い | 例外 | false | 例外 |
| 不正文字の扱い | 例外 | false | 例外 |
| 実務での安全性 | 低め | 高い | 条件付きで便利 |
| 主な用途 | 値が保証されている変換 | 入力値・外部データの変換 | 汎用的な変換 |
実務では、まずTryParseを候補にするのが安全です。
6-2. 例外が発生する条件の違い
ParseとConvertは、変換できない値に対して例外を発生させます。
C#int.Parse("abc"); // FormatException
Convert.ToInt32("abc"); // FormatException
一方、TryParseは例外を発生させず、falseを返します。
C#bool result = int.TryParse("abc", out int value);
Console.WriteLine(result); // false
例外は本来、予期しない異常を扱う仕組みです。ユーザー入力のミスのように日常的に起こるものは、例外ではなく条件分岐で処理する方が適しています。
6-3. null・空文字・不正文字への対応の違い
null、空文字、不正文字に対する動作を比較してみましょう。
C#string? nullText = null;
string emptyText = "";
string invalidText = "abc";
| 入力値 | int.Parse | int.TryParse | Convert.ToInt32 |
|---|---|---|---|
null | 例外 | false | 0 |
"" | 例外 | false | 例外 |
"abc" | 例外 | false | 例外 |
"123" | 123 | true | 123 |
Convert.ToInt32(null)が0になる点は、便利でもあり危険でもあります。
未入力をエラーにしたい場合は、Convertに任せず、明示的にチェックしましょう。
6-4. 戻り値とエラーハンドリングの違い
Parseは変換結果そのものを返します。
C#int value = int.Parse("123");
失敗時は例外処理が必要です。
C#try
{
int value = int.Parse("abc");
}
catch (FormatException)
{
Console.WriteLine("数値形式が不正です。");
}
TryParseは成功・失敗をboolで返します。
C#if (int.TryParse("123", out int value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("変換できません。");
}
ConvertはParseと同じように変換結果を返しますが、nullの扱いが異なります。
C#int value = Convert.ToInt32(null);
Console.WriteLine(value); // 0
6-5. 実務ではTryParseを優先すべき理由
実務では、次のような理由からTryParseを優先するのがおすすめです。
| 理由 | 内容 |
|---|---|
| 例外を防げる | 不正入力でもアプリが止まりにくい |
| 入力チェックと相性がよい | エラーメッセージを表示しやすい |
| 外部データに強い | CSV、API、フォーム入力に対応しやすい |
| 意図が明確 | 「失敗する可能性がある変換」と分かる |
特に、ユーザー入力や外部データを扱う場合は、TryParseを使うことで安全で読みやすいコードになります。
C#string input = "100";
if (!int.TryParse(input, out int value))
{
Console.WriteLine("数値を入力してください。");
return;
}
Console.WriteLine($"変換結果: {value}");
7. 数値型同士の変換方法
7-1. intからdouble・decimalへ変換する
intからdoubleやdecimalへの変換は、暗黙的に行えます。
C#int intValue = 100;
double doubleValue = intValue;
decimal decimalValue = intValue;
Console.WriteLine(doubleValue); // 100
Console.WriteLine(decimalValue); // 100
このような変換では、通常データの損失が起こりにくいため、キャストを書く必要はありません。
7-2. doubleからintへ変換する
doubleからintへ変換する場合、小数点以下が失われる可能性があるため、明示的なキャストが必要です。
C#double doubleValue = 123.45;
int intValue = (int)doubleValue;
Console.WriteLine(intValue); // 123
キャストでは、小数点以下は0に近づく方向に切り捨てられます。
C#Console.WriteLine((int)123.99); // 123
Console.WriteLine((int)-123.99); // -123
四捨五入したい場合は、Math.Roundなどを使います。
C#double value = 123.5;
int rounded = (int)Math.Round(value);
Console.WriteLine(rounded);
7-3. キャストによる明示的変換
キャストは、型を明示して変換する方法です。
C#double value = 10.5;
int number = (int)value;
longからintのように、範囲が狭くなる変換にもキャストを使います。
C#long longValue = 100;
int intValue = (int)longValue;
ただし、変換先の型に収まらない値をキャストすると、期待しない結果になることがあります。
C#long longValue = 3000000000;
int intValue = (int)longValue;
Console.WriteLine(intValue); // 想定外の値になる可能性
安全に確認したい場合はcheckedを使います。
C#long longValue = 3000000000;
try
{
int intValue = checked((int)longValue);
}
catch (OverflowException)
{
Console.WriteLine("intの範囲を超えています。");
}
7-4. Convert.ToInt32とキャストの違い
Convert.ToInt32とキャストは、小数を整数に変換するときの挙動が異なります。
C#double value = 123.6;
int castValue = (int)value;
int convertValue = Convert.ToInt32(value);
Console.WriteLine(castValue); // 123
Console.WriteLine(convertValue); // 124
キャストは小数点以下を切り捨てます。
一方、Convert.ToInt32は丸め処理を行います。
さらに、.5のような中間値では、最も近い偶数に丸められる点にも注意が必要です。
C#Console.WriteLine(Convert.ToInt32(2.5)); // 2
Console.WriteLine(Convert.ToInt32(3.5)); // 4
これは、一般的な「必ず0.5以上を切り上げる四捨五入」とは異なる場合があります。
7-5. 小数を整数に変換するときの丸め処理
小数を整数に変換するときは、目的に応じて方法を選びます。
| 処理 | 使用する方法 |
|---|---|
| 小数点以下を切り捨てる | キャスト、Math.Truncate |
| 四捨五入する | Math.Round |
| 切り上げる | Math.Ceiling |
| 切り下げる | Math.Floor |
Convertの丸めを使う | Convert.ToInt32 |
例です。
C#double value = 123.45;
Console.WriteLine((int)value); // 123
Console.WriteLine(Math.Round(value)); // 123
Console.WriteLine(Math.Ceiling(value)); // 124
Console.WriteLine(Math.Floor(value)); // 123
Console.WriteLine(Math.Truncate(value)); // 123
負の数では、FloorとTruncateの結果が異なる点に注意しましょう。
C#double value = -123.45;
Console.WriteLine(Math.Floor(value)); // -124
Console.WriteLine(Math.Truncate(value)); // -123
8. 数値変換で発生するエラーと対処法
8-1. FormatExceptionの原因と対処法
FormatExceptionは、文字列が数値として解釈できない場合に発生します。
C#int value = int.Parse("abc");
主な原因は次の通りです。
| 原因 | 例 |
|---|---|
| 数字以外の文字が含まれる | "abc" |
| 空文字 | "" |
| 記号が不正 | "12-3" |
| カンマや通貨記号の扱いが不適切 | "1,000"、"¥100" |
| 小数を整数として変換しようとする | "123.45" |
対処法は、TryParseを使うことです。
C#string input = "abc";
if (!int.TryParse(input, out int value))
{
Console.WriteLine("整数を入力してください。");
}
8-2. OverflowExceptionの原因と対処法
OverflowExceptionは、値が変換先の型の範囲を超えている場合に発生します。
C#int value = int.Parse("999999999999");
intに収まらない可能性がある場合は、まずlongで受ける、またはTryParseで判定します。
C#string input = "999999999999";
if (long.TryParse(input, out long longValue))
{
Console.WriteLine(longValue);
}
else
{
Console.WriteLine("数値が大きすぎます。");
}
intとして扱いたい場合は、範囲チェックも行います。
C#string input = "999999999999";
if (!long.TryParse(input, out long value))
{
Console.WriteLine("数値ではありません。");
return;
}
if (value < int.MinValue || value > int.MaxValue)
{
Console.WriteLine("intの範囲を超えています。");
return;
}
int intValue = (int)value;
なお、doubleでは非常に大きな値が無限大として扱われるケースもあるため、必要に応じてdouble.IsInfinityも確認します。
C#if (double.TryParse("1e9999", out double result))
{
if (double.IsInfinity(result))
{
Console.WriteLine("値が大きすぎます。");
}
}
8-3. ArgumentNullExceptionが関係するケース
Parseにnullを渡すと、ArgumentNullExceptionが発生します。
C#string? input = null;
int value = int.Parse(input);
TryParseであれば、nullを渡しても例外ではなくfalseになります。
C#string? input = null;
if (int.TryParse(input, out int value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("値が入力されていません。");
}
Convert.ToInt32(null)は0になります。
C#int value = Convert.ToInt32(null);
Console.WriteLine(value); // 0
そのため、nullをエラーとして扱いたいのか、0として扱いたいのかを明確にしておくことが重要です。
8-4. 全角数字・カンマ・空白を含む文字列への対応
実務では、次のような文字列を数値変換したい場合があります。
C#"123"
"1,000"
" 123 "
"¥1,000"
前後の空白は、TryParseで処理できる場合があります。
C#int.TryParse(" 123 ", out int value);
Console.WriteLine(value); // 123
カンマ区切りを許可したい場合は、NumberStyles.AllowThousandsを指定します。
C#using System.Globalization;
string input = "1,000";
bool success = int.TryParse(
input,
NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
out int value
);
Console.WriteLine(success); // true
Console.WriteLine(value); // 1000
通貨記号を含む場合は、NumberStyles.Currencyを使う方法もあります。
C#using System.Globalization;
string input = "¥1,000";
bool success = decimal.TryParse(
input,
NumberStyles.Currency,
CultureInfo.GetCultureInfo("ja-JP"),
out decimal value
);
Console.WriteLine(success);
Console.WriteLine(value);
全角数字は、そのままでは期待通りに変換できないことがあるため、半角へ正規化してから変換するのが安全です。
C#string input = "123";
string normalized = input
.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');
if (int.TryParse(normalized, out int value))
{
Console.WriteLine(value);
}
8-5. 例外を出さない安全な変換コードの書き方
例外を出さずに安全に変換する基本形は、次の通りです。
C#string? input = "123";
if (!int.TryParse(input, out int value))
{
Console.WriteLine("数値に変換できません。");
return;
}
Console.WriteLine($"変換結果: {value}");
空文字や空白を事前にチェックしたい場合は、string.IsNullOrWhiteSpaceを組み合わせます。
C#string? input = " ";
if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("値を入力してください。");
return;
}
if (!int.TryParse(input, out int value))
{
Console.WriteLine("整数を入力してください。");
return;
}
Console.WriteLine(value);
実務では、次の順番でチェックすると分かりやすくなります。
未入力チェック
数値形式チェック
範囲チェック
業務ルールチェック
C#string? input = "150";
if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("年齢を入力してください。");
return;
}
if (!int.TryParse(input, out int age))
{
Console.WriteLine("年齢は整数で入力してください。");
return;
}
if (age < 0 || age > 120)
{
Console.WriteLine("年齢は0〜120の範囲で入力してください。");
return;
}
Console.WriteLine($"年齢: {age}");
9. 実務で使える数値変換のサンプルコード
9-1. テキストボックスの入力値をintに変換する
Windows FormsやWPF、ASP.NETなどでテキストボックスの値を数値に変換する場合は、TryParseを使います。
C#string input = textBoxAge.Text;
if (!int.TryParse(input, out int age))
{
MessageBox.Show("年齢は整数で入力してください。");
return;
}
if (age < 0 || age > 120)
{
MessageBox.Show("年齢は0〜120の範囲で入力してください。");
return;
}
// 正常処理
MessageBox.Show($"入力された年齢: {age}");
Webアプリケーションでも考え方は同じです。
C#string? input = Request.Form["quantity"];
if (!int.TryParse(input, out int quantity))
{
ModelState.AddModelError("quantity", "数量は整数で入力してください。");
return View();
}
if (quantity <= 0)
{
ModelState.AddModelError("quantity", "数量は1以上で入力してください。");
return View();
}
9-2. CSVの文字列データをdecimalに変換する
CSVで金額を扱う場合は、decimal.TryParseを使います。
C#using System.Globalization;
string csvAmount = "1234.56";
if (!decimal.TryParse(
csvAmount,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal amount))
{
Console.WriteLine("金額データが不正です。");
return;
}
Console.WriteLine($"金額: {amount}");
カンマ付きの金額を許可したい場合は、NumberStyles.Numberを指定します。
C#using System.Globalization;
string csvAmount = "1,234.56";
bool success = decimal.TryParse(
csvAmount,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal amount
);
if (success)
{
Console.WriteLine(amount);
}
CSVは外部データなので、Parseで一気に変換するより、TryParseで不正データを検出する方が安全です。
9-3. APIレスポンスの数値文字列を変換する
APIレスポンスで数値が文字列として返ってくる場合もあります。
JSON{
"price": "1980.50",
"quantity": "3"
}
C#側では、次のように変換できます。
C#using System.Globalization;
string priceText = "1980.50";
string quantityText = "3";
if (!decimal.TryParse(
priceText,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out decimal price))
{
Console.WriteLine("価格の形式が不正です。");
return;
}
if (!int.TryParse(quantityText, out int quantity))
{
Console.WriteLine("数量の形式が不正です。");
return;
}
decimal total = price * quantity;
Console.WriteLine($"合計: {total}");
APIでは、国や環境に依存しない形式で数値が返ることが多いため、CultureInfo.InvariantCultureを指定しておくと安全です。
9-4. 入力エラー時にメッセージを表示する
入力エラー時には、単に「エラー」と表示するのではなく、ユーザーが修正しやすいメッセージにします。
C#string? input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("数量を入力してください。");
return;
}
if (!int.TryParse(input, out int quantity))
{
Console.WriteLine("数量は整数で入力してください。");
return;
}
if (quantity <= 0)
{
Console.WriteLine("数量は1以上で入力してください。");
return;
}
Console.WriteLine($"数量: {quantity}");
エラーメッセージは、次のように分けると親切です。
| 状況 | メッセージ例 |
|---|---|
| 未入力 | 値を入力してください |
| 数値形式ではない | 数値で入力してください |
| 整数ではない | 整数で入力してください |
| 範囲外 | 1〜100の範囲で入力してください |
9-5. 共通メソッド化して再利用しやすくする
同じような数値変換処理が複数箇所にある場合は、共通メソッド化すると便利です。
C#public static bool TryConvertToInt(
string? input,
int min,
int max,
out int value,
out string errorMessage)
{
value = 0;
errorMessage = string.Empty;
if (string.IsNullOrWhiteSpace(input))
{
errorMessage = "値を入力してください。";
return false;
}
if (!int.TryParse(input, out value))
{
errorMessage = "整数で入力してください。";
return false;
}
if (value < min || value > max)
{
errorMessage = $"{min}〜{max}の範囲で入力してください。";
return false;
}
return true;
}
使用例です。
C#if (TryConvertToInt("150", 0, 120, out int age, out string error))
{
Console.WriteLine($"年齢: {age}");
}
else
{
Console.WriteLine(error);
}
decimal用の共通メソッドも作れます。
C#using System.Globalization;
public static bool TryConvertToDecimal(
string? input,
out decimal value,
out string errorMessage)
{
value = 0;
errorMessage = string.Empty;
if (string.IsNullOrWhiteSpace(input))
{
errorMessage = "値を入力してください。";
return false;
}
if (!decimal.TryParse(
input,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out value))
{
errorMessage = "数値で入力してください。";
return false;
}
return true;
}
共通メソッド化することで、入力チェックのルールを統一でき、保守性も高くなります。
10. C#の数値変換でよくある質問
10-1. ParseとTryParseはどちらを使えばいいか
基本的には、TryParseを使うのがおすすめです。
Parseは、値が必ず正しいと分かっている場合に使います。
C#int value = int.Parse("123");
一方、ユーザー入力やCSV、APIなど、値が不正である可能性がある場合はTryParseを使います。
C#if (int.TryParse(input, out int value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値ではありません。");
}
実務では、不正な値が入る可能性を考慮して、TryParseを優先すると安全です。
10-2. Convert.ToInt32とint.Parseの違いは何か
大きな違いは、nullを渡した場合の動作です。
C#string? text = null;
Console.WriteLine(Convert.ToInt32(text)); // 0
Console.WriteLine(int.Parse(text)); // 例外
Convert.ToInt32(null)は0になりますが、int.Parse(null)は例外になります。
また、Convert.ToInt32は文字列以外の型も変換できます。
C#double value = 123.6;
int result = Convert.ToInt32(value);
Console.WriteLine(result); // 124
ただし、不正な文字列ではConvertでも例外が発生します。
C#Convert.ToInt32("abc"); // FormatException
10-3. 文字列がnullのときはどう変換されるか
文字列がnullの場合、変換方法によって動作が異なります。
| 方法 | 結果 |
|---|---|
int.Parse(null) | 例外 |
int.TryParse(null, out value) | false |
Convert.ToInt32(null) | 0 |
安全に処理するなら、TryParseを使うか、事前にnullチェックを行います。
C#string? input = null;
if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("値が入力されていません。");
return;
}
if (int.TryParse(input, out int value))
{
Console.WriteLine(value);
}
nullを0として扱う仕様ならConvertでもよいですが、未入力をエラーにしたい場合は注意が必要です。
10-4. 小数を整数に変換すると四捨五入されるのか
変換方法によって異なります。
キャストでは、小数点以下が切り捨てられます。
C#double value = 123.9;
int result = (int)value;
Console.WriteLine(result); // 123
Convert.ToInt32では丸め処理が行われます。
C#double value = 123.9;
int result = Convert.ToInt32(value);
Console.WriteLine(result); // 124
ただし、.5の場合は最も近い偶数に丸められる点に注意してください。
C#Console.WriteLine(Convert.ToInt32(2.5)); // 2
Console.WriteLine(Convert.ToInt32(3.5)); // 4
一般的な四捨五入を明示したい場合は、Math.Roundを使い、必要に応じて丸め方法を指定します。
C#double value = 2.5;
int result = (int)Math.Round(
value,
MidpointRounding.AwayFromZero
);
Console.WriteLine(result); // 3
10-5. decimal・double・floatはどう使い分けるべきか
decimal、double、floatは、扱える範囲や精度、用途が異なります。
| 型 | 主な用途 | 特徴 |
|---|---|---|
decimal | 金額、会計、税計算 | 10進数の精度を重視 |
double | 一般的な小数、科学計算 | 範囲が広く計算が速い |
float | ゲーム、画像処理、大量データ | メモリ使用量が少ない |
金額計算では、基本的にdecimalを使います。
C#decimal price = 100.25m;
decimal tax = 0.10m;
decimal total = price * (1 + tax);
一般的な測定値や割合、座標などではdoubleを使うことが多いです。
C#double rate = 0.12345;
double distance = 123.456;
floatは精度よりもメモリ効率を重視する場面で使われます。
C#float x = 1.23f;
迷った場合は、金額ならdecimal、それ以外の一般的な小数ならdoubleを選ぶとよいでしょう。
まとめ
C#の数値変換には、Parse、TryParse、Convert、キャストなど複数の方法があります。
それぞれの特徴を整理すると、次のようになります。
| 方法 | 使う場面 |
|---|---|
Parse | 値が必ず正しいと保証できる場合 |
TryParse | ユーザー入力や外部データなど、不正値の可能性がある場合 |
Convert | nullを0として扱いたい場合や汎用的な変換をしたい場合 |
| キャスト | 数値型同士を明示的に変換したい場合 |
実務で最も重要なのは、失敗する可能性がある変換ではTryParseを使うことです。
C#if (int.TryParse(input, out int value))
{
Console.WriteLine(value);
}
else
{
Console.WriteLine("数値に変換できません。");
}
Parseはシンプルですが、不正な値で例外が発生します。Convertは便利ですが、nullを0にするため、未入力を見逃す可能性があります。キャストは数値型同士の変換に使えますが、小数点以下の切り捨てや桁あふれに注意が必要です。
C#の数値変換では、値の入力元、失敗時の扱い、nullや空文字の扱い、丸め処理、カルチャ差を意識することが大切です。特に、画面入力、CSV、APIレスポンスなどの外部データでは、TryParseを中心にした安全な変換処理を書くことで、例外や不具合を防ぎやすくなります。

