C# String Formatの使い方を徹底解説|文字列の書式指定・0埋め・日付・数値フォーマットまでわかる

はじめに

C#で文字列を作るとき、変数の値を文章の中に埋め込んだり、数値を3桁区切りにしたり、日付をyyyy/MM/dd形式で表示したりしたい場面はよくあります。そこで使える代表的な方法がString.Formatです。

String.Formatを使うと、単に値を文字列に変換するだけでなく、表示形式を細かく指定できます。たとえば、金額を1,200円のように表示する、IDを0001のように0埋めする、ログ用の日付を2026-06-06 10:30:00のように整える、といった処理を簡潔に書けます。

この記事では、C#のString.Formatの基本構文から、文字列の書式指定、0埋め、日付、時刻、数値フォーマット、桁揃え、文字列補間式との違いまで、実務で使える形で解説します。

1. C#のString.Formatとは?まず押さえるべき基本

1-1. String.Formatでできること

String.Formatは、指定した書式に従って値を文字列に変換し、その結果を別の文字列の中に埋め込むためのメソッドです。Microsoftの公式ドキュメントでも、String.Formatはオブジェクトの値を書式に基づいて文字列化し、別の文字列へ挿入するメソッドとして説明されています。

たとえば、次のように名前や年齢を文章に埋め込めます。

C#
string name = "田中";
int age = 30;

string message = String.Format("{0}さんは{1}歳です。", name, age);

Console.WriteLine(message);

出力結果は次のとおりです。

田中さんは30歳です。

{0}{1}の部分はプレースホルダーと呼ばれ、後ろに渡した値に置き換えられます。

1-2. 文字列連結・Console.WriteLine・ToStringとの違い

C#で文字列を作る方法はString.Formatだけではありません。代表的な方法には、文字列連結、Console.WriteLineToString、文字列補間式があります。

文字列連結は、+を使って文字列をつなげる方法です。

C#
string message = name + "さんは" + age + "歳です。";

短い文字列なら問題ありませんが、値が増えると読みづらくなります。

Console.WriteLineでも、String.Formatと似た書式を使えます。

C#
Console.WriteLine("{0}さんは{1}歳です。", name, age);

ただし、Console.WriteLineはコンソールへ直接出力するためのメソッドです。文字列として変数に保持したい場合はString.Formatを使います。

ToStringは、値そのものを文字列に変換するときに使います。

C#
int number = 123;
string text = number.ToString();

一方、String.Formatは複数の値を1つの文章に埋め込むときに便利です。

1-3. String.Formatが使われる主な場面

String.Formatは、次のような場面でよく使われます。

C#
string priceText = String.Format("価格:{0:N0}円", 12000);
string dateText = String.Format("処理日:{0:yyyy/MM/dd}", DateTime.Now);
string idText = String.Format("会員ID:{0:D6}", 25);

主な用途は、ユーザー向けメッセージの生成、ログメッセージの整形、金額や数量の表示、日付や時刻の表示、ファイル名や管理番号の生成、固定幅のテキスト出力などです。

特に、表示形式を統一したい処理ではString.Formatが役立ちます。

1-4. この記事で学べる書式指定の全体像

String.Formatで重要なのは、プレースホルダーと書式指定子です。

基本形は次のようになります。

C#
String.Format("{0:書式}", )

たとえば、数値を3桁区切りにする場合は次のように書きます。

C#
String.Format("{0:N0}", 1234567)

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

1,234,567

日付を指定形式で表示する場合は、次のように書きます。

C#
String.Format("{0:yyyy/MM/dd}", DateTime.Now)

このように、String.Formatでは、文字列の中に値を入れるだけでなく、数値、日付、時刻、桁数、0埋め、左右寄せなどを細かく制御できます。

2. String.Formatの基本構文とプレースホルダーの使い方

2-1. 基本構文:String.Format("文字列{0}", 値)

String.Formatの基本構文は次のとおりです。

C#
String.Format("文字列{0}", )

{0}の部分に、後ろで指定した値が入ります。

C#
string result = String.Format("こんにちは、{0}さん。", "佐藤");

Console.WriteLine(result);

出力結果は次のとおりです。

こんにちは、佐藤さん。

String.Formatは、指定したフォーマット文字列をもとに、新しい文字列を返します。元の文字列を直接変更するわけではありません。

2-2. {0}・{1}・{2}の意味と引数の対応関係

{0}{1}{2}は、後ろに渡した引数の順番に対応します。インデックスは0から始まります。

C#
string result = String.Format(
"商品名:{0}、価格:{1}円、在庫:{2}個",
"ノート",
120,
35
);

Console.WriteLine(result);

出力結果は次のとおりです。

商品名:ノート、価格:120円、在庫:35個

対応関係は次のようになります。

{0} → "ノート"
{1} → 120
{2} → 35

String.Formatでは、プレースホルダーのインデックスと引数の数が合っている必要があります。公式ドキュメントでも、書式項目には0から始まる数値インデックスを指定し、そのインデックスに対応する引数が必要と説明されています。

2-3. 同じ値を複数回使う方法

同じ値を複数回使いたい場合は、同じインデックスを何度でも指定できます。

C#
string name = "山田";

string result = String.Format("{0}さん、こんにちは。{0}さんの注文を確認しました。", name);

Console.WriteLine(result);

出力結果は次のとおりです。

山田さん、こんにちは。山田さんの注文を確認しました。

引数を何度も渡す必要はありません。同じ値を複数箇所に表示したい場合は、同じ{0}を繰り返し使えます。

2-4. 複数の値を1つの文字列に埋め込む方法

複数の値を埋め込む場合は、{0}{1}{2}のようにインデックスを増やします。

C#
string userName = "鈴木";
int point = 1500;
DateTime expireDate = new DateTime(2026, 12, 31);

string message = String.Format(
"{0}さんの保有ポイントは{1}ポイントです。有効期限は{2:yyyy/MM/dd}です。",
userName,
point,
expireDate
);

Console.WriteLine(message);

出力結果は次のようになります。

鈴木さんの保有ポイントは1500ポイントです。有効期限は2026/12/31です。

この例では、{2:yyyy/MM/dd}のように日付の書式も同時に指定しています。

2-5. 波括弧{}を文字として表示する方法

String.Formatでは、{}はプレースホルダーとして解釈されます。そのため、波括弧そのものを文字として表示したい場合は、{{}}のように2つ重ねます。

C#
string result = String.Format("JSONの例:{{ \"name\": \"{0}\" }}", "田中");

Console.WriteLine(result);

出力結果は次のとおりです。

JSONの例:{ "name": "田中" }

波括弧のエスケープ忘れは、String.Formatでよくあるエラーの1つです。JSON、テンプレート、正規表現風の文字列などを扱うときは特に注意しましょう。

3. C# String.Formatの書式指定子の基本

3-1. 書式指定子とは何か

書式指定子とは、値をどのような形式で文字列に変換するかを指定する記号です。

たとえば、数値を小数点以下2桁で表示したい場合は、次のように書きます。

C#
double value = 123.456;

string result = String.Format("{0:F2}", value);

Console.WriteLine(result);

出力結果は次のとおりです。

123.46

F2は固定小数点形式で小数点以下2桁を表します。

3-2. {0:書式}の基本パターン

String.Formatで書式を指定する基本形は次のとおりです。

C#
{インデックス:書式}

具体例は次のようになります。

C#
String.Format("{0:N0}", 1234567)
String.Format("{0:F2}", 123.456)
String.Format("{0:yyyy/MM/dd}", DateTime.Now)
String.Format("{0:D5}", 42)

それぞれの意味は次のとおりです。

{0:N0}        3桁区切り、小数点以下0桁
{0:F2} 小数点以下2桁
{0:yyyy/MM/dd} 年/月/日
{0:D5} 5桁の整数、足りない桁は0埋め

3-3. 標準書式指定子とカスタム書式指定子の違い

C#の書式指定には、大きく分けて標準書式指定子とカスタム書式指定子があります。

標準書式指定子は、NFCPDなど、あらかじめ用意された短い記号です。たとえばN0は3桁区切りの数値、Cは通貨、Pはパーセントを表します。標準数値書式指定子には、通貨形式のC、10進整数のD、固定小数点のF、数値形式のN、パーセント形式のPなどがあります。

C#
string result = String.Format("{0:N0}", 1234567);

カスタム書式指定子は、0#,.yyyyMMddなどを組み合わせて、自分で表示形式を作る方法です。

C#
string result = String.Format("{0:00000}", 123);

出力結果は次のとおりです。

00123

柔軟に指定したい場合はカスタム書式、よくある形式を簡単に使いたい場合は標準書式を使うとよいでしょう。

3-4. よく使う書式指定子一覧

よく使う数値の書式指定子は次のとおりです。

書式意味
N03桁区切り、小数なし1,234
N23桁区切り、小数2桁1,234.50
F2小数点以下2桁1234.50
C通貨形式¥1,234
P1パーセント形式、小数1桁12.3%
D4整数を4桁で0埋め0025
00004桁の0埋め0025

よく使う日付・時刻の書式指定子は次のとおりです。

書式意味
yyyy4桁の年2026
MM2桁の月06
dd2桁の日06
HH24時間表記の時15
mm30
ss45
ddd曜日の省略名
dddd曜日名土曜日

日付や時刻のカスタム書式では、yyyyMMddHHmmssなどの指定子を組み合わせて表示形式を作れます。

3-5. 書式指定でエラーになりやすいポイント

String.Formatでエラーになりやすいのは、次のようなケースです。

C#
// 引数が足りない
String.Format("{0} {1}", "A");

// 波括弧の閉じ忘れ
String.Format("値は {0", 100);

// 波括弧を文字として表示したいのにエスケープしていない
String.Format("値は { test }");

また、数値用の書式を日付に使う、日付用の書式を数値に使うなど、型と書式指定が合っていない場合にも意図しない結果や例外につながることがあります。

4. 数値をString.Formatでフォーマットする方法

4-1. 小数点以下の桁数を指定する

小数点以下の桁数を指定するには、Fを使います。

C#
double value = 123.4567;

string result = String.Format("{0:F2}", value);

Console.WriteLine(result);

出力結果は次のとおりです。

123.46

F2は小数点以下2桁、F3は小数点以下3桁です。

C#
Console.WriteLine(String.Format("{0:F1}", 123.4567));
Console.WriteLine(String.Format("{0:F3}", 123.4567));

出力結果は次のようになります。

123.5
123.457

表示桁数に合わせて丸めが行われます。

4-2. 3桁区切りのカンマを付ける

3桁区切りのカンマを付けたい場合は、Nを使います。

C#
int amount = 1234567;

string result = String.Format("{0:N0}", amount);

Console.WriteLine(result);

出力結果は次のとおりです。

1,234,567

小数点以下2桁まで表示したい場合は、N2を使います。

C#
double amount = 1234567.8;

string result = String.Format("{0:N2}", amount);

Console.WriteLine(result);

出力結果は次のようになります。

1,234,567.80

金額、数量、集計値などを見やすく表示したいときに便利です。

4-3. 通貨形式で表示する

通貨形式で表示するには、Cを使います。

C#
int price = 1200;

string result = String.Format("{0:C}", price);

Console.WriteLine(result);

日本語環境では、出力は次のようになることがあります。

¥1,200

C0のように指定すると、小数点以下の桁数を制御できます。

C#
Console.WriteLine(String.Format("{0:C0}", 1200));
Console.WriteLine(String.Format("{0:C2}", 1200));

通貨記号や区切り文字はカルチャの影響を受けます。日本語環境では円、米国英語環境ではドルのように、実行環境や指定したカルチャによって表示が変わります。

4-4. パーセント形式で表示する

パーセント形式で表示するには、Pを使います。

C#
double rate = 0.1234;

string result = String.Format("{0:P1}", rate);

Console.WriteLine(result);

出力結果は次のようになります。

12.3%

Pは値を100倍してパーセント記号を付けます。0.25P0で表示すると、25%になります。

C#
Console.WriteLine(String.Format("{0:P0}", 0.25));

出力結果は次のとおりです。

25%

割合、達成率、進捗率、割引率などの表示に使えます。

4-5. プラス・マイナスなど符号を制御する

正の数に+を付けたい場合は、カスタム数値書式を使います。

C#
int value1 = 10;
int value2 = -5;

Console.WriteLine(String.Format("{0:+0;-0;0}", value1));
Console.WriteLine(String.Format("{0:+0;-0;0}", value2));
Console.WriteLine(String.Format("{0:+0;-0;0}", 0));

出力結果は次のとおりです。

+10
-5
0

カスタム数値書式では、セミコロンで正の値、負の値、ゼロの表示形式を分けられます。

正の値の書式;負の値の書式;ゼロの書式

増減値や差分を表示する場合に便利です。

C#
int diff = 8;

string result = String.Format("前月比:{0:+0;-0;0}件", diff);

Console.WriteLine(result);

出力結果は次のとおりです。

前月比:+8件

4-6. 数値フォーマットの実用例

実務では、数値フォーマットを次のように使えます。

C#
int sales = 12345678;
double rate = 0.873;
int diff = -120;

string message = String.Format(
"売上:{0:N0}円、達成率:{1:P1}、前年差:{2:+0;-0;0}円",
sales,
rate,
diff
);

Console.WriteLine(message);

出力結果は次のようになります。

売上:12,345,678円、達成率:87.3%、前年差:-120円

数値をそのまま表示するより、書式を指定したほうが読みやすく、ユーザーにも伝わりやすい表示になります。

5. String.Formatで0埋めする方法

5-1. 数値を指定桁数で0埋めする

数値を0埋めするには、Dまたはカスタム書式の0を使います。

整数を4桁で0埋めする例です。

C#
int number = 25;

string result = String.Format("{0:D4}", number);

Console.WriteLine(result);

出力結果は次のとおりです。

0025

カスタム書式でも同じように書けます。

C#
string result = String.Format("{0:0000}", number);

こちらも出力結果は次のとおりです。

0025

D4は整数向けの標準書式、0000はカスタム書式です。

5-2. ID・連番・コードを0埋めする例

会員ID、注文番号、商品コードなどでは、桁数をそろえるために0埋めを使うことがあります。

C#
int userId = 123;

string userCode = String.Format("USER-{0:D6}", userId);

Console.WriteLine(userCode);

出力結果は次のとおりです。

USER-000123

連番付きのファイル名にも使えます。

C#
int index = 7;

string fileName = String.Format("image_{0:D3}.png", index);

Console.WriteLine(fileName);

出力結果は次のとおりです。

image_007.png

桁数をそろえることで、文字列として並べたときにも順番が崩れにくくなります。

5-3. 小数点を含む数値を0埋めする方法

小数点を含む数値を0埋めしたい場合は、カスタム書式を使います。

C#
double value = 12.3;

string result = String.Format("{0:000.00}", value);

Console.WriteLine(result);

出力結果は次のとおりです。

012.30

整数部分は3桁、小数部分は2桁で表示されます。

別の例も見てみましょう。

C#
Console.WriteLine(String.Format("{0:0000.000}", 5.2));

出力結果は次のとおりです。

0005.200

0は、値が存在しない桁にも0を表示するためのプレースホルダーです。

5-4. 0埋めと桁数指定の注意点

D4のような標準書式は整数型に対して使います。doubledecimalなどの小数を含む型にDを使うと適切ではありません。

C#
int number = 12345;

string result = String.Format("{0:D4}", number);

Console.WriteLine(result);

この場合、指定桁数より実際の桁数が多いため、出力は次のようになります。

12345

D4は「最大4桁に切り詰める」という意味ではありません。最低4桁になるように0を補う指定です。元の数値の桁数が多い場合は、そのまま表示されます。

5-5. ToString("D4")との使い分け

0埋めだけをしたい場合は、ToString("D4")でも書けます。

C#
int number = 25;

string result = number.ToString("D4");

Console.WriteLine(result);

出力結果は次のとおりです。

0025

一方、文章の中に埋め込みたい場合はString.Formatが便利です。

C#
int number = 25;

string result = String.Format("注文番号:{0:D4}", number);

Console.WriteLine(result);

出力結果は次のとおりです。

注文番号:0025

値単体を文字列化するならToString、文章全体を整形するならString.Format、という使い分けがわかりやすいです。

6. 日付・時刻をString.Formatでフォーマットする方法

6-1. yyyy/MM/dd形式で日付を表示する

日付をyyyy/MM/dd形式で表示するには、次のように書きます。

C#
DateTime date = new DateTime(2026, 6, 6);

string result = String.Format("{0:yyyy/MM/dd}", date);

Console.WriteLine(result);

出力結果は次のとおりです。

2026/06/06

yyyyは4桁の年、MMは2桁の月、ddは2桁の日を表します。

ハイフン区切りにしたい場合は、次のように書きます。

C#
string result = String.Format("{0:yyyy-MM-dd}", date);

出力結果は次のとおりです。

2026-06-06

6-2. HH:mm:ss形式で時刻を表示する

時刻をHH:mm:ss形式で表示するには、次のように書きます。

C#
DateTime time = new DateTime(2026, 6, 6, 15, 30, 45);

string result = String.Format("{0:HH:mm:ss}", time);

Console.WriteLine(result);

出力結果は次のとおりです。

15:30:45

HHは24時間表記の時、mmは分、ssは秒です。

注意したいのは、月は大文字のMM、分は小文字のmmである点です。

C#
String.Format("{0:yyyy/MM/dd HH:mm:ss}", DateTime.Now)

このように日付と時刻を組み合わせることもできます。

6-3. 年・月・日・曜日を個別に指定する

年、月、日、曜日を個別に指定することもできます。

C#
DateTime date = new DateTime(2026, 6, 6);

string result = String.Format("{0:yyyy年MM月dd日 dddd}", date);

Console.WriteLine(result);

日本語環境では、出力結果は次のようになります。

2026年06月06日 土曜日

曜日を短く表示したい場合はdddを使います。

C#
string result = String.Format("{0:yyyy/MM/dd (ddd)}", date);

出力例は次のとおりです。

2026/06/06 (土)

曜日表記もカルチャの影響を受けるため、実行環境によって表示言語が変わる場合があります。

6-4. ログやファイル名に使える日付フォーマット

ログやファイル名では、並び替えや検索がしやすい形式にすることが重要です。

ログメッセージの例です。

C#
DateTime now = DateTime.Now;

string log = String.Format("[{0:yyyy-MM-dd HH:mm:ss}] 処理を開始しました。", now);

Console.WriteLine(log);

出力例は次のとおりです。

[2026-06-06 15:30:45] 処理を開始しました。

ファイル名に使う場合は、/:などファイル名に使えない文字を避けます。

C#
DateTime now = DateTime.Now;
int index = 1;

string fileName = String.Format("log_{0:yyyyMMdd_HHmmss}_{1:D3}.txt", now, index);

Console.WriteLine(fileName);

出力例は次のとおりです。

log_20260606_153045_001.txt

yyyyMMdd_HHmmss形式は、ログファイル、バックアップファイル、エクスポートファイルなどでよく使われます。

6-5. 日本語表記の日付フォーマット

日本語の画面表示では、年月日を日本語表記にしたいことがあります。

C#
DateTime date = new DateTime(2026, 6, 6);

string result = String.Format("{0:yyyy年M月d日}", date);

Console.WriteLine(result);

出力結果は次のとおりです。

2026年6月6日

MMddを使うと2桁表示になり、Mdを使うと必要な桁だけ表示されます。

C#
Console.WriteLine(String.Format("{0:yyyy年MM月dd日}", date));
Console.WriteLine(String.Format("{0:yyyy年M月d日}", date));

出力結果は次のとおりです。

2026年06月06日
2026年6月6日

帳票や管理画面ではyyyy年MM月dd日、自然な文章ではyyyy年M月d日のように使い分けるとよいでしょう。

6-6. DateTime.ToStringとの違い

日付だけを文字列化する場合は、DateTime.ToStringでも十分です。

C#
DateTime date = new DateTime(2026, 6, 6);

string result = date.ToString("yyyy/MM/dd");

一方、文章の中に日付を埋め込む場合はString.Formatが便利です。

C#
DateTime date = new DateTime(2026, 6, 6);

string result = String.Format("登録日は{0:yyyy/MM/dd}です。", date);

出力結果は次のとおりです。

登録日は2026/06/06です。

日付単体ならToString、複数の値を組み合わせたメッセージならString.Formatを使うと読みやすくなります。

7. 桁揃え・右寄せ・左寄せの使い方

7-1. 桁幅を指定して右寄せする

String.Formatでは、値を指定した幅で右寄せできます。構文は次のとおりです。

C#
{インデックス,}

たとえば、5文字幅で右寄せするには次のように書きます。

C#
Console.WriteLine(String.Format("|{0,5}|", 123));

出力結果は次のとおりです。

|  123|

123の前に空白が入り、全体が5文字幅になります。

7-2. マイナス指定で左寄せする

左寄せしたい場合は、幅にマイナスを付けます。

C#
Console.WriteLine(String.Format("|{0,-5}|", 123));

出力結果は次のとおりです。

|123  |

文字列にも使えます。

C#
Console.WriteLine(String.Format("|{0,-10}|", "Apple"));

出力結果は次のとおりです。

|Apple     |

表形式のテキストを作る場合に便利です。

7-3. 表形式の出力を整える方法

コンソールやログで表のように表示したい場合、桁幅指定を使うと見やすくなります。

C#
Console.WriteLine(String.Format("{0,-10} {1,8} {2,8}", "商品", "単価", "数量"));
Console.WriteLine(String.Format("{0,-10} {1,8:N0} {2,8:N0}", "ノート", 120, 15));
Console.WriteLine(String.Format("{0,-10} {1,8:N0} {2,8:N0}", "ペン", 80, 120));
Console.WriteLine(String.Format("{0,-10} {1,8:N0} {2,8:N0}", "ファイル", 350, 6));

出力結果は次のようになります。

商品               単価       数量
ノート 120 15
ペン 80 120
ファイル 350 6

英数字中心のデータでは整列しやすいですが、日本語はフォントや表示環境によって幅がずれることがあります。コンソール出力では、等幅フォントを使うと見やすくなります。

7-4. 数値と文字列を混在させて整列する例

数値と文字列を混在させる場合、文字列は左寄せ、数値は右寄せにすると読みやすくなります。

C#
string name = "田中";
int score = 95;
double rate = 0.875;

string result = String.Format("{0,-8} {1,5:N0}点 {2,8:P1}", name, score, rate);

Console.WriteLine(result);

出力結果は次のようになります。

田中          95点    87.5%

書式指定と桁揃えは同時に使えます。

C#
{0,8:N0}

これは、{0}の値をN0形式で表示し、8文字幅で右寄せする指定です。

8. 文字列補間式との違いと使い分け

8-1. String.Formatと$"{ }"の違い

C#では、String.Formatのほかに文字列補間式もよく使われます。

C#
string name = "田中";
int age = 30;

string message = $"{name}さんは{age}歳です。";

これは、次のString.Formatと同じような結果になります。

C#
string message = String.Format("{0}さんは{1}歳です。", name, age);

文字列補間式は、変数名をそのまま書けるため、可読性が高いのが特徴です。Microsoftの公式ドキュメントでも、対応言語ではString.Formatや複合書式指定の代わりに補間文字列を使えると説明されています。

8-2. 文字列補間式で同じ書式指定をする方法

文字列補間式でも、String.Formatと同じように書式指定ができます。

C#
int amount = 1234567;
DateTime date = new DateTime(2026, 6, 6);

string message = $"金額:{amount:N0}円、日付:{date:yyyy/MM/dd}";

Console.WriteLine(message);

出力結果は次のとおりです。

金額:1,234,567円、日付:2026/06/06

0埋めも同じように書けます。

C#
int id = 25;

string code = $"ID-{id:D4}";

Console.WriteLine(code);

出力結果は次のとおりです。

ID-0025

8-3. 可読性を重視するならどちらを使うべきか

新しく書くコードで、フォーマット文字列が固定されている場合は、文字列補間式のほうが読みやすいことが多いです。

C#
string message = $"{name}さんの購入金額は{amount:N0}円です。";

String.Formatで書くと次のようになります。

C#
string message = String.Format("{0}さんの購入金額は{1:N0}円です。", name, amount);

値が少ない場合はどちらでもよいですが、引数が増えると{0}{1}が何を指しているのか追いにくくなります。

そのため、可読性を重視するなら文字列補間式、既存コードとの統一や動的なフォーマットが必要な場合はString.Format、という使い分けが現実的です。

8-4. 既存コード・動的フォーマットでString.Formatが向くケース

String.Formatが向いているのは、フォーマット文字列を外部から受け取る場合や、既存コードでString.Formatが使われている場合です。

C#
string template = "{0}さん、{1}件の通知があります。";

string message = String.Format(template, "田中", 5);

Console.WriteLine(message);

出力結果は次のとおりです。

田中さん、5件の通知があります。

テンプレートを設定ファイル、データベース、リソースファイルなどで管理する場合は、String.Formatが扱いやすいです。

多言語対応でも、文の順番が言語によって変わることがあるため、{0}{1}で値の位置を制御できるString.Formatが役立ちます。

9. String.Formatのよくあるエラーと対処法

9-1. FormatExceptionが発生する原因

String.Formatでは、書式文字列が不正な場合にFormatExceptionが発生します。公式ドキュメントでも、formatが無効な場合や、書式項目のインデックスが指定範囲外の場合にFormatExceptionが発生すると説明されています。

たとえば、次のコードはエラーになります。

C#
string result = String.Format("値は {0", 100);

波括弧が閉じられていないため、正しい書式として解釈できません。

正しくは次のように書きます。

C#
string result = String.Format("値は {0}", 100);

9-2. 引数の数とプレースホルダーが合わない場合

プレースホルダーに対応する引数がない場合もエラーになります。

C#
string result = String.Format("{0} {1}", "A");

{1}に対応する2つ目の引数がないため、例外が発生します。

正しくは次のように、必要な数の引数を渡します。

C#
string result = String.Format("{0} {1}", "A", "B");

または、不要なプレースホルダーを削除します。

C#
string result = String.Format("{0}", "A");

プレースホルダーの番号と引数の数は必ず確認しましょう。

9-3. 波括弧のエスケープ忘れ

波括弧を文字として表示したい場合は、{{}}を使います。

悪い例です。

C#
string result = String.Format("オブジェクト: { name: {0} }", "田中");

このように書くと、{ name: ... }の部分が書式として解釈され、エラーになることがあります。

正しくは次のように書きます。

C#
string result = String.Format("オブジェクト: {{ name: {0} }}", "田中");

出力結果は次のとおりです。

オブジェクト: { name: 田中 }

JSON風の文字列を作るときは、特に波括弧のエスケープに注意が必要です。

9-4. 書式指定子の型が合わない場合

数値用、日付用、整数用の書式指定を混同すると、エラーや意図しない表示の原因になります。

たとえば、D4は整数の0埋めに使う書式です。

C#
int id = 25;
string result = String.Format("{0:D4}", id);

これは問題ありません。

一方、小数に対して整数向けの書式を使うのは適切ではありません。

C#
double value = 12.3;

// 避けたい例
string result = String.Format("{0:D4}", value);

小数を含む数値を0埋めしたい場合は、次のようにカスタム書式を使います。

C#
double value = 12.3;

string result = String.Format("{0:000.00}", value);

型に合った書式指定子を使うことが大切です。

9-5. nullを渡した場合の挙動

String.Formatに値としてnullを渡した場合、通常は空文字列として扱われます。

C#
string name = null;

string result = String.Format("名前:{0}", name);

Console.WriteLine(result);

出力結果は次のようになります。

名前:

ただし、フォーマット文字列そのものがnullの場合は例外になります。

C#
string result = String.Format(null, "A");

フォーマット文字列は必ず有効な文字列を指定しましょう。

nullの値を明示的に表示したい場合は、事前に変換しておくと安全です。

C#
string name = null;

string result = String.Format("名前:{0}", name ?? "未設定");

Console.WriteLine(result);

出力結果は次のとおりです。

名前:未設定

10. 実務で使えるString.Formatのサンプル集

10-1. 請求金額や価格を表示する

金額を表示する場合は、3桁区切りを使うと読みやすくなります。

C#
int subtotal = 12000;
int tax = 1200;
int total = subtotal + tax;

string message = String.Format(
"小計:{0:N0}円、消費税:{1:N0}円、合計:{2:N0}円",
subtotal,
tax,
total
);

Console.WriteLine(message);

出力結果は次のとおりです。

小計:12,000円、消費税:1,200円、合計:13,200円

通貨形式を使う場合は次のように書けます。

C#
string message = String.Format("請求金額:{0:C0}", total);

カルチャによって通貨記号が変わる点には注意しましょう。

10-2. ログメッセージを整形する

ログでは、日時、ログレベル、処理内容を一定の形式で出力すると確認しやすくなります。

C#
DateTime now = DateTime.Now;
string level = "INFO";
string action = "ユーザー情報を更新しました";

string log = String.Format("[{0:yyyy-MM-dd HH:mm:ss}] [{1}] {2}", now, level, action);

Console.WriteLine(log);

出力例は次のとおりです。

[2026-06-06 15:30:45] [INFO] ユーザー情報を更新しました

ログ形式を統一しておくと、検索や集計もしやすくなります。

10-3. ファイル名に日付や連番を入れる

エクスポートファイルやバックアップファイルでは、日付や連番をファイル名に含めることがあります。

C#
DateTime now = DateTime.Now;
int sequence = 8;

string fileName = String.Format("export_{0:yyyyMMdd}_{1:D3}.csv", now, sequence);

Console.WriteLine(fileName);

出力例は次のとおりです。

export_20260606_008.csv

時刻まで入れる場合は次のようにします。

C#
string fileName = String.Format("backup_{0:yyyyMMdd_HHmmss}.zip", DateTime.Now);

出力例は次のとおりです。

backup_20260606_153045.zip

ファイル名では、/:のような使用できない文字を避けるのがポイントです。

10-4. CSVや固定長テキストを作成する

CSVの1行を作る場合にもString.Formatを使えます。

C#
int id = 1;
string name = "田中";
int amount = 12000;

string csv = String.Format("{0},{1},{2}", id, name, amount);

Console.WriteLine(csv);

出力結果は次のとおりです。

1,田中,12000

ただし、値にカンマや改行、ダブルクォーテーションが含まれる可能性がある場合は、CSV専用のライブラリやエスケープ処理を使うべきです。

固定長テキストを作る場合は、桁幅指定が便利です。

C#
string line = String.Format("{0:D5}{1,-10}{2,8:N0}", 1, "Tanaka", 12000);

Console.WriteLine(line);

出力例は次のとおりです。

00001Tanaka      12,000

固定長ファイルでは、文字コードや全角文字の扱いにも注意が必要です。

10-5. ユーザー向けメッセージを生成する

画面表示や通知メッセージでも、String.Formatはよく使えます。

C#
string userName = "佐藤";
int count = 3;
DateTime limit = new DateTime(2026, 6, 30);

string message = String.Format(
"{0}さん、未確認のお知らせが{1}件あります。確認期限は{2:yyyy年M月d日}です。",
userName,
count,
limit
);

Console.WriteLine(message);

出力結果は次のとおりです。

佐藤さん、未確認のお知らせが3件あります。確認期限は2026年6月30日です。

ユーザー向けの文章では、単に値を入れるだけでなく、日付や数値を読みやすい形式に整えることが大切です。

11. String.Formatを使うときの注意点とベストプラクティス

11-1. 可読性を下げない書き方

String.Formatは便利ですが、引数が増えると読みにくくなります。

C#
string message = String.Format("{0} {1} {2} {3}", a, b, c, d);

このようなコードでは、{2}が何を表しているのかすぐにわかりません。

可読性を保つには、次のような工夫が有効です。

C#
string message = String.Format(
"商品名:{0}、価格:{1:N0}円、数量:{2:N0}個",
productName,
price,
quantity
);

フォーマット文字列をわかりやすくし、引数名も意味のある名前にすると、保守しやすくなります。

新規コードでは、文字列補間式を使ったほうが読みやすい場合もあります。

C#
string message = $"商品名:{productName}、価格:{price:N0}円、数量:{quantity:N0}個";

11-2. カルチャによる表示の違いに注意する

数値、通貨、日付の表示はカルチャの影響を受けます。

C#
decimal price = 1234.5m;

string result = String.Format("{0:C}", price);

日本語環境では円表記、米国英語環境ではドル表記になるなど、実行環境によって結果が変わる場合があります。String.Formatには、カルチャ固有の書式情報を渡せるオーバーロードも用意されています。

表示を固定したい場合は、CultureInfoを明示します。

C#
using System.Globalization;

decimal price = 1234.5m;

string jp = String.Format(new CultureInfo("ja-JP"), "{0:C}", price);
string us = String.Format(new CultureInfo("en-US"), "{0:C}", price);

Console.WriteLine(jp);
Console.WriteLine(us);

出力例は次のようになります。

¥1,235
$1,234.50

ユーザーの言語や地域に合わせるのか、システムとして固定表示にするのかを意識して使い分けましょう。

11-3. パフォーマンスを意識すべきケース

通常の画面表示やログ出力であれば、String.Formatのパフォーマンスを過度に気にする必要はありません。

ただし、大量のループ内で何万回、何百万回も文字列を生成する場合は注意が必要です。

C#
for (int i = 0; i < 100000; i++)
{
string line = String.Format("No:{0:D6}", i);
}

このような処理では、文字列生成の回数が多くなります。大量の文字列を連結する場合は、StringBuilderの利用を検討します。

C#
var builder = new System.Text.StringBuilder();

for (int i = 0; i < 1000; i++)
{
builder.AppendFormat("No:{0:D6}", i);
builder.AppendLine();
}

string result = builder.ToString();

実務では、まず読みやすさを優先し、明らかに処理回数が多い部分だけパフォーマンスを検討するとよいでしょう。

11-4. 文字列補間式・ToString・StringBuilderとの使い分け

String.Format、文字列補間式、ToStringStringBuilderは、それぞれ得意な場面が異なります。

方法向いている場面
String.Formatテンプレート文字列に値を埋め込む、既存コードに合わせる
文字列補間式新規コードで読みやすく書きたい
ToString値単体を指定形式で文字列化したい
StringBuilder大量の文字列を繰り返し連結したい

たとえば、値単体ならToStringが簡潔です。

C#
string id = number.ToString("D4");

文章に埋め込むなら、文字列補間式またはString.Formatが向いています。

C#
string message1 = $"IDは{number:D4}です。";
string message2 = String.Format("IDは{0:D4}です。", number);

外部テンプレートを使う場合はString.Formatが便利です。

C#
string template = "IDは{0:D4}です。";
string message = String.Format(template, number);

状況に応じて使い分けることで、読みやすく保守しやすいコードになります。

まとめ

String.Formatは、C#で文字列を整形するための基本的で強力なメソッドです。{0}{1}のようなプレースホルダーを使って値を埋め込み、{0:N0}{0:F2}{0:D4}{0:yyyy/MM/dd}のように書式指定を追加することで、数値、日付、時刻、0埋め、桁揃えなどを柔軟に表現できます。

数値では、N0で3桁区切り、F2で小数点以下2桁、Cで通貨形式、Pでパーセント形式を指定できます。0埋めでは、整数ならD4、小数を含む場合は000.00のようなカスタム書式が便利です。日付では、yyyy/MM/ddHH:mm:ssyyyyMMdd_HHmmssなどを使い分けることで、画面表示、ログ、ファイル名などに適した形式を作れます。

一方で、String.Formatは引数が増えると可読性が下がりやすいため、新規コードでは文字列補間式のほうが読みやすい場合もあります。値単体の変換にはToString、大量の文字列結合にはStringBuilder、外部テンプレートや既存コードとの統一にはString.Formatを使うなど、目的に応じて選ぶことが大切です。

String.Formatの基本を理解しておくと、C#の文字列処理、ログ出力、画面表示、帳票作成、ファイル名生成など、さまざまな場面で役立ちます。まずは、{0}で値を埋め込む基本形と、{0:書式}で表示形式を指定する形を確実に押さえておきましょう。