「C#のToString()ってよく出てくるけど、いまいちピンとこない…」
そんな疑問を持つ方は多いのではないでしょうか?
ToString()は、C#のすべてのオブジェクトが持っているメソッドで、その名の通り、オブジェクトを文字列に変換するための機能です。
この記事では、ToString()の基本的な使い方から、カスタマイズ方法、そしてよくある落とし穴まで、初心者にもわかりやすく丁寧に解説していきます。
ToString()の基本構文と動作

最もシンプルな使い方
int num = 123;
string text = num.ToString();
Console.WriteLine(text); // "123"
いろいろな型での使用例
// 整数
int integer = 42;
string intText = integer.ToString(); // "42"
// 小数
double decimal = 3.14159;
string decimalText = decimal.ToString(); // "3.14159"
// 真偽値
bool flag = true;
string boolText = flag.ToString(); // "True"
// 日付
DateTime today = DateTime.Now;
string dateText = today.ToString(); // "2025/06/03 14:30:45"
ToString()の仕組み
すべてのクラスはObjectクラスを継承
// これらは同じ意味
object obj = 123;
string result1 = obj.ToString();
int num = 123;
string result2 = num.ToString();
内部では何が起こっている?
- オブジェクトの型を確認
- その型に定義されたToString()メソッドを実行
- 文字列として返す
いつToString()を使うの?
コンソール出力
int score = 85;
Console.WriteLine("あなたの点数は" + score.ToString() + "点です");
ログ出力
int userId = 12345;
Log.Info("ユーザーID: " + userId.ToString() + "がログインしました");
UI表示(WinFormsやWPF)
int count = 10;
label1.Text = count.ToString();
数値のフォーマット指定

基本的なフォーマット指定
double price = 1234.567;
// 小数点以下の桁数を指定
string f2 = price.ToString("F2"); // "1234.57"
string f0 = price.ToString("F0"); // "1235"
// 3桁区切りのカンマ
string n2 = price.ToString("N2"); // "1,234.57"
string n0 = price.ToString("N0"); // "1,235"
// 通貨形式
string currency = price.ToString("C"); // "¥1,235"
よく使うフォーマット一覧
| フォーマット | 説明 | 例(1234.567) |
|---|---|---|
"F2" | 小数点以下2桁 | 1234.57 |
"F0" | 整数部分のみ | 1235 |
"N0" | 3桁区切り(整数) | 1,235 |
"N2" | 3桁区切り(小数2桁) | 1,234.57 |
"C" | 通貨形式 | ¥1,235 |
"P" | パーセント形式 | 123,456.70% |
"E2" | 指数形式 | 1.23E+003 |
実際の使用例
// 商品価格の表示
double itemPrice = 1980;
Console.WriteLine($"価格: {itemPrice.ToString("C")}"); // "価格: ¥1,980"
// 割引率の表示
double discountRate = 0.15;
Console.WriteLine($"割引率: {discountRate.ToString("P0")}"); // "割引率: 15%"
// 統計データの表示
double average = 87.654321;
Console.WriteLine($"平均点: {average.ToString("F1")}"); // "平均点: 87.7"
ゼロ埋めの指定
int number = 5;
// ゼロ埋めで指定桁数にする
string d3 = number.ToString("D3"); // "005"
string d5 = number.ToString("D5"); // "00005"
// 16進数表示
string hex = number.ToString("X2"); // "05"
string hexUpper = number.ToString("X4"); // "0005"
日付・時刻のフォーマット指定
基本的な日付フォーマット
DateTime now = new DateTime(2025, 6, 3, 14, 30, 45);
// 年月日
string date1 = now.ToString("yyyy/MM/dd"); // "2025/06/03"
string date2 = now.ToString("yyyy-MM-dd"); // "2025-06-03"
string date3 = now.ToString("MM/dd/yyyy"); // "06/03/2025"
// 時刻
string time1 = now.ToString("HH:mm:ss"); // "14:30:45"
string time2 = now.ToString("hh:mm tt"); // "02:30 PM"
// 日付と時刻
string datetime1 = now.ToString("yyyy/MM/dd HH:mm:ss"); // "2025/06/03 14:30:45"
string datetime2 = now.ToString("MM/dd/yyyy hh:mm tt"); // "06/03/2025 02:30 PM"
よく使う日付フォーマット一覧
| フォーマット | 説明 | 例 |
|---|---|---|
"yyyy" | 4桁の年 | 2025 |
"MM" | 2桁の月 | 06 |
"dd" | 2桁の日 | 03 |
"HH" | 24時間形式の時 | 14 |
"hh" | 12時間形式の時 | 02 |
"mm" | 分 | 30 |
"ss" | 秒 | 45 |
"tt" | AM/PM | PM |
"ddd" | 曜日(短縮形) | Tue |
"dddd" | 曜日(完全形) | Tuesday |
実際の使用例
DateTime now = DateTime.Now;
// ログファイル名用
string logFileName = now.ToString("yyyyMMdd") + ".log"; // "20250603.log"
// ユーザー表示用
string userDisplay = now.ToString("yyyy年M月d日 H時m分"); // "2025年6月3日 14時30分"
// システム間のデータ交換用(ISO形式)
string isoFormat = now.ToString("yyyy-MM-ddTHH:mm:ss"); // "2025-06-03T14:30:45"
// 日本語の曜日表示
System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("ja-JP");
string japaneseDay = now.ToString("yyyy年M月d日(ddd)", culture); // "2025年6月3日(火)"
カスタムクラスでのToString()のオーバーライド
基本的なオーバーライド
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public override string ToString()
{
return $"商品名: {Name}, 価格: {Price:C}, カテゴリ: {Category}";
}
}
使用例
Product product = new Product
{
Name = "りんご",
Price = 150,
Category = "果物"
};
Console.WriteLine(product.ToString());
// 出力: 商品名: りんご, 価格: ¥150, カテゴリ: 果物
より実践的な例
顧客情報クラス
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime RegisterDate { get; set; }
public override string ToString()
{
return $"[ID:{Id}] {Name} ({Email}) - 登録日: {RegisterDate:yyyy/MM/dd}";
}
}
注文情報クラス
public class Order
{
public int OrderId { get; set; }
public Customer Customer { get; set; }
public List<Product> Items { get; set; }
public DateTime OrderDate { get; set; }
public override string ToString()
{
decimal total = Items?.Sum(item => item.Price) ?? 0;
int itemCount = Items?.Count ?? 0;
return $"注文#{OrderId} - {Customer?.Name} - " +
$"商品数: {itemCount}, 合計: {total:C} ({OrderDate:yyyy/MM/dd})";
}
}
デバッグ時の活用
public class BankAccount
{
public string AccountNumber { get; set; }
public string OwnerName { get; set; }
public decimal Balance { get; set; }
public override string ToString()
{
// デバッグ時に便利な情報を含める
return $"口座[{AccountNumber}] {OwnerName} 残高:{Balance:C}";
}
}
// デバッグ時の確認が楽になる
BankAccount account = new BankAccount
{
AccountNumber = "1234567890",
OwnerName = "田中太郎",
Balance = 50000
};
Console.WriteLine($"処理対象: {account}");
// 出力: 処理対象: 口座[1234567890] 田中太郎 残高:¥50,000
より高度なToString()の使い方

IFormattableインターフェースの実装
public class Temperature : IFormattable
{
public double Celsius { get; set; }
public override string ToString()
{
return ToString("C", null);
}
public string ToString(string format)
{
return ToString(format, null);
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (string.IsNullOrEmpty(format)) format = "C";
switch (format.ToUpperInvariant())
{
case "C":
return $"{Celsius:F1}°C";
case "F":
return $"{(Celsius * 9.0 / 5.0) + 32:F1}°F";
case "K":
return $"{Celsius + 273.15:F1}K";
default:
throw new FormatException($"'{format}' は無効なフォーマットです");
}
}
}
使用例
Temperature temp = new Temperature { Celsius = 25.0 };
Console.WriteLine(temp.ToString()); // "25.0°C"
Console.WriteLine(temp.ToString("F")); // "77.0°F"
Console.WriteLine(temp.ToString("K")); // "298.1K"
複雑なオブジェクトの文字列化
public class Report
{
public string Title { get; set; }
public DateTime GeneratedAt { get; set; }
public List<string> Data { get; set; }
public Dictionary<string, object> Metadata { get; set; }
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"=== {Title} ===");
sb.AppendLine($"生成日時: {GeneratedAt:yyyy/MM/dd HH:mm:ss}");
sb.AppendLine($"データ件数: {Data?.Count ?? 0}");
if (Metadata?.Any() == true)
{
sb.AppendLine("メタデータ:");
foreach (var kvp in Metadata)
{
sb.AppendLine($" {kvp.Key}: {kvp.Value}");
}
}
return sb.ToString();
}
}
よくある間違いと対処法
1. nullオブジェクトに対するToString()
問題のあるコード
Product product = null;
Console.WriteLine(product.ToString()); // ❌ NullReferenceException
解決方法1: null チェック
Product product = null;
if (product != null)
{
Console.WriteLine(product.ToString());
}
else
{
Console.WriteLine("商品情報がありません");
}
解決方法2: null条件演算子
Product product = null;
Console.WriteLine(product?.ToString() ?? "商品情報がありません");
解決方法3: 拡張メソッド
public static class ObjectExtensions
{
public static string ToStringSafe(this object obj, string defaultValue = "")
{
return obj?.ToString() ?? defaultValue;
}
}
// 使用例
Product product = null;
Console.WriteLine(product.ToStringSafe("商品なし"));
2. 不正なフォーマット文字列
問題のあるコード
int value = 1000;
Console.WriteLine(value.ToString("Z")); // ❌ FormatException
解決方法: try-catch で例外処理
int value = 1000;
string format = "Z";
try
{
string result = value.ToString(format);
Console.WriteLine(result);
}
catch (FormatException)
{
Console.WriteLine($"無効なフォーマット '{format}' です。標準形式で表示: {value}");
}
3. 文化・地域設定の違い
問題:異なる地域での表示が変わる
double price = 1234.56;
DateTime date = new DateTime(2025, 6, 3);
// システムの地域設定によって結果が変わる
Console.WriteLine(price.ToString("C")); // 日本: ¥1,235, アメリカ: $1,234.56
Console.WriteLine(date.ToString("d")); // 日本: 2025/06/03, アメリカ: 6/3/2025
解決方法: CultureInfo を明示的に指定
using System.Globalization;
double price = 1234.56;
DateTime date = new DateTime(2025, 6, 3);
// 日本の形式で統一
CultureInfo jpCulture = new CultureInfo("ja-JP");
Console.WriteLine(price.ToString("C", jpCulture)); // ¥1,235
Console.WriteLine(date.ToString("d", jpCulture)); // 2025/06/03
// アメリカの形式で統一
CultureInfo usCulture = new CultureInfo("en-US");
Console.WriteLine(price.ToString("C", usCulture)); // $1,234.56
Console.WriteLine(date.ToString("d", usCulture)); // 6/3/2025
ToString()とその他の文字列化手法の比較
文字列補間(String Interpolation)との使い分け
int age = 25;
string name = "田中";
// ToString()を明示的に使用
string message1 = "私の名前は" + name + "で、年齢は" + age.ToString() + "歳です";
// 文字列補間(推奨)
string message2 = $"私の名前は{name}で、年齢は{age}歳です";
// String.Format
string message3 = String.Format("私の名前は{0}で、年齢は{1}歳です", name, age);
それぞれの特徴
| 方法 | メリット | デメリット | 使用場面 |
|---|---|---|---|
| ToString() | 明示的、カスタマイズ可能 | 冗長になりがち | カスタムフォーマットが必要 |
| 文字列補間 ($””) | 読みやすい、簡潔 | .NET Framework 4.6以降 | 一般的な文字列作成 |
| String.Format | 多言語対応しやすい | 可読性が低い | ローカライゼーション |
パフォーマンスの考慮

StringBuilder との使い分け
小規模な文字列結合
// これで十分
string result = $"{user.Name} ({user.Age}歳) - {user.Email}";
大量の文字列結合
// StringBuilderを使用(高速)
var sb = new StringBuilder();
foreach (var item in largeList)
{
sb.AppendLine(item.ToString());
}
string result = sb.ToString();
キャッシュの活用
public class Product
{
private string _cachedString = null;
public string Name { get; set; }
public decimal Price { get; set; }
public override string ToString()
{
// 値が変更されていない場合はキャッシュを返す
if (_cachedString == null)
{
_cachedString = $"{Name} - {Price:C}";
}
return _cachedString;
}
// プロパティ変更時にキャッシュをクリア
private void ClearCache()
{
_cachedString = null;
}
}
実際の開発での活用例
ログ出力
public class Logger
{
public static void LogInfo(object obj)
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Console.WriteLine($"[INFO] {timestamp}: {obj?.ToString() ?? "null"}");
}
}
// 使用例
Product product = new Product { Name = "りんご", Price = 150 };
Logger.LogInfo(product);
// 出力: [INFO] 2025-06-03 14:30:45: 商品名: りんご, 価格: ¥150
デバッグ支援
public static class DebugHelper
{
public static void PrintObject(object obj, string label = "Object")
{
Console.WriteLine($"=== {label} ===");
if (obj == null)
{
Console.WriteLine("null");
}
else
{
Console.WriteLine($"Type: {obj.GetType().Name}");
Console.WriteLine($"Value: {obj}");
}
Console.WriteLine();
}
}
API レスポンス
public class ApiResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public object Data { get; set; }
public override string ToString()
{
return $"ApiResponse [Success: {Success}, Message: '{Message}', Data: {Data?.ToString() ?? "null"}]";
}
}
まとめ
C#のToString()メソッドは、単なる文字列変換以上の価値を持つ強力な機能です。
重要なポイント
- すべてのオブジェクトがToString()メソッドを持っている
- フォーマット指定で数値や日付を見やすく表示できる
- オーバーライドでカスタムクラスの表示内容をカスタマイズ可能
- null安全性やエラーハンドリングが重要
使い方のコツ
- デバッグ時にわかりやすい文字列になるようオーバーライドする
- 適切なフォーマット指定でユーザビリティを向上させる
- null チェックやエラーハンドリングを忘れない
- パフォーマンスが重要な場面では StringBuilder の使用を検討
よく使う場面
- ログ出力とデバッグ
- ユーザーへの表示
- ファイル名や識別子の生成
- API レスポンスの文字列化


コメント