C#文字列操作の基本を完全解説|結合・分割・置換・検索・比較まで初心者向けにわかる
はじめに
C#でアプリケーションを開発するとき、文字列操作は避けて通れない基本技術です。コンソールへのメッセージ表示、ユーザー入力のチェック、CSVデータの処理、ファイルパスの生成など、さまざまな場面で文字列を扱います。
C#では文字列をstring型として扱い、結合・分割・置換・検索・比較といった処理を標準機能だけで実装できます。ただし、nullと空文字の違い、文字列が変更できないイミュータブルな型であること、大文字小文字や日本語を比較するときの注意点など、初心者がつまずきやすいポイントもあります。
この記事では、C#の文字列操作について、基本的な書き方から実践的なサンプルまで順番に解説します。
1. C#の文字列とは?初心者が最初に押さえる基本
1-1. C#における文字列はstring型で扱う
C#では、複数の文字からなるデータをstring型で扱います。
string message = "こんにちは";string name = "田中";一方、1文字だけを扱う場合はchar型を使用します。
char grade = 'A';string型の文字列はダブルクォート、char型の文字はシングルクォートで囲む点が重要です。
string text = "A";char character = 'A';見た目は似ていますが、textは文字列、characterは1文字を表す値です。
1-2. stringとStringの違い
C#では、次の2つの書き方が使用できます。
string message1 = "Hello";String message2 = "Hello";stringは、.NETのSystem.String型に対するC#のキーワードです。そのため、次の3つは基本的に同じ型を表します。
string message1 = "Hello";String message2 = "Hello";System.String message3 = "Hello";一般的なC#のコーディングでは、変数の型を宣言するときはstringを使うことが推奨されます。
string name = "佐藤";静的メソッドを呼び出す場合も、次のようにstringと書けます。
bool isEmpty = string.IsNullOrEmpty(name);Stringを使っても動作は変わりませんが、プロジェクト内で表記を統一することが大切です。
1-3. 文字列リテラルの書き方
プログラム内に直接記述した文字列を、文字列リテラルと呼びます。
string message = "C#を学習しています";Windowsのファイルパスのように、バックスラッシュが多い文字列では逐語的文字列リテラルを使うと読みやすくなります。文字列の先頭に@を付けます。
string path = @"C:\Users\user\Documents\sample.txt";通常の文字列では、バックスラッシュを2つ重ねる必要があります。
string path = "C:\\Users\\user\\Documents\\sample.txt";複数行のテキストを記述する場合は、C# 11以降で利用できる生文字列リテラルも便利です。
string json = """{"name": "田中","age": 30}""";生文字列リテラルでは、ダブルクォートや改行を比較的そのまま記述できます。
1-4. エスケープシーケンスと改行・タブ・ダブルクォートの表現
文字列の中で改行やタブ、ダブルクォートなどを表現するには、エスケープシーケンスを使用します。
代表的なエスケープシーケンスは次のとおりです。
| 書き方 | 意味 |
|---|---|
\n | 改行 |
\r | キャリッジリターン |
\t | タブ |
\" | ダブルクォート |
\\ | バックスラッシュ |
\0 | null文字 |
改行を含む文字列は、次のように記述します。
string message = "1行目\n2行目";Console.WriteLine(message);実行結果は次のとおりです。
1行目2行目文字列内にダブルクォートを表示する場合は、\"を使います。
string message = "彼は\"こんにちは\"と言いました。";Console.WriteLine(message);タブを挿入する場合は\tを使用します。
Console.WriteLine("商品名\t価格");Console.WriteLine("りんご\t120円");実行環境に適した改行を入れたい場合は、Environment.NewLineも利用できます。
string message = "1行目" + Environment.NewLine + "2行目";1-5. 文字列は変更できない「イミュータブル」な型
C#のstringは、作成された後に内容を変更できないイミュータブルな型です。
たとえば、Replaceメソッドで文字列を置換しても、元の文字列自体は変更されません。
string original = "C#入門";string replaced = original.Replace("入門", "基礎");Console.WriteLine(original); // C#入門Console.WriteLine(replaced); // C#基礎
次のコードでは、戻り値を変数に代入していないため、結果は変わりません。
string text = "abc";text.Replace("a", "A");Console.WriteLine(text); // abc
置換結果を反映するには、戻り値を受け取ります。
text = text.Replace("a", "A");Console.WriteLine(text); // Abc
文字列を何度も変更すると、そのたびに新しい文字列が作られます。大量の文字列を繰り返し結合する処理では、後述するStringBuilderの利用を検討しましょう。
2. C#で文字列を宣言・代入・表示する方法
2-1. string変数の宣言と初期化
文字列変数は、次のように宣言します。
string message;宣言と同時に値を代入することもできます。
string message = "こんにちは";型推論を利用して、varで宣言することも可能です。
var message = "こんにちは";この場合、右辺が文字列なので、messageはstring型として扱われます。ただし、型が分かりにくくなる場面では明示的にstringと書いたほうが読みやすい場合があります。
変数に別の文字列を再代入することもできます。
string status = "処理前";status = "処理完了";2-2. Console.WriteLineで文字列を出力する
コンソールに文字列を表示するには、Console.WriteLineを使用します。
Console.WriteLine("こんにちは");変数の内容も出力できます。
string name = "山田";Console.WriteLine(name);Console.WriteLineは、出力後に改行します。
Console.WriteLine("1行目");Console.WriteLine("2行目");改行せずに続けて表示したい場合は、Console.Writeを使用します。
Console.Write("名前:");Console.Write("山田");実行結果は次のようになります。
名前:山田2-3. nullと空文字の違い
nullと空文字は異なる状態です。
string? value1 = null;string value2 = "";nullは、文字列オブジェクトが存在しない状態です。一方、""は長さが0の文字列が存在している状態です。
空白だけを含む文字列も、空文字とは異なります。
string value3 = " ";それぞれの状態を整理すると、次のようになります。
| 値 | 状態 |
null | 文字列が存在しない |
"" | 長さ0の文字列 |
" " | 半角スペースを1文字含む文字列 |
" " | 全角スペースを1文字含む文字列 |
nullの変数に対してLengthなどのインスタンスメンバーを呼び出すと、NullReferenceExceptionが発生します。
string? text = null;Console.WriteLine(text.Length); // 例外が発生する可能性がある2-4. string.Emptyの使い方
string.Emptyは、空文字を表すプロパティです。
string value1 = "";string value2 = string.Empty;value1とvalue2の内容は同じです。
Console.WriteLine(value1 == value2); // True""とstring.Emptyのどちらを使っても、通常は動作や性能に実質的な違いはありません。プロジェクトのコーディング規約に合わせて統一しましょう。
空文字かどうかを調べるだけなら、直接比較するよりstring.IsNullOrEmptyを使うと、nullも同時に確認できます。
string? input = "";if (string.IsNullOrEmpty(input)){Console.WriteLine("値が入力されていません");}
2-5. 文字列の長さをLengthで取得する
文字列の長さは、Lengthプロパティで取得できます。
string text = "Hello";Console.WriteLine(text.Length); // 5
日本語も取得できます。
string text = "こんにちは";Console.WriteLine(text.Length); // 5
空文字の長さは0です。
string text = string.Empty;Console.WriteLine(text.Length); // 0
ただし、nullに対してLengthを呼び出すことはできません。事前にnullを確認します。
string? text = null;if (text is not null){Console.WriteLine(text.Length);}
null条件演算子を使って、次のように書くこともできます。
int? length = text?.Length;なお、Lengthは内部的なUTF-16コード単位の数を返します。一般的な日本語では見た目の文字数と一致しやすいものの、一部の絵文字や結合文字では、見た目の1文字がLengthでは2以上になることがあります。
3. C#で文字列を結合する方法
3-1. +演算子で文字列を結合する
最も簡単な文字列結合は、+演算子を使う方法です。
string firstName = "太郎";string lastName = "山田";string fullName = lastName + firstName;
Console.WriteLine(fullName); // 山田太郎
間にスペースを入れることもできます。
string fullName = lastName + " " + firstName;文字列と数値を結合すると、数値は文字列に変換されます。
int age = 25;string message = "年齢は" + age + "歳です。";Console.WriteLine(message);
少数の文字列を単純に結合する場合は、+演算子で問題ありません。
3-2. 文字列補間で読みやすく結合する
文字列補間では、文字列の先頭に$を付け、変数や式を{}の中に記述します。
string name = "田中";int age = 30;string message = $"名前は{name}、年齢は{age}歳です。";
Console.WriteLine(message);
+演算子を多用するよりも、完成形が分かりやすくなります。
計算式も埋め込めます。
int price = 1000;int quantity = 3;Console.WriteLine($"合計金額は{price * quantity}円です。");
書式指定も可能です。
decimal price = 123456.78m;Console.WriteLine($"価格:{price:N0}円");
実行結果は、一般的な日本語環境では次のようになります。
価格:123,457円日付の書式も指定できます。
DateTime today = DateTime.Today;Console.WriteLine($"日付:{today:yyyy年MM月dd日}");
3-3. string.Concatで複数の文字列を結合する
string.Concatを使って、複数の文字列を結合できます。
string result = string.Concat("C#", "の", "文字列", "操作");Console.WriteLine(result); // C#の文字列操作
配列の要素を区切り文字なしで連結することもできます。
string[] words = { "A", "B", "C" };string result = string.Concat(words);
Console.WriteLine(result); // ABC
区切り文字を入れたい場合は、string.Joinのほうが適しています。
3-4. string.Joinで配列やリストを区切り文字付きで結合する
string.Joinは、配列やリストの要素を指定した区切り文字で結合します。
string[] fruits = { "りんご", "みかん", "ぶどう" };string result = string.Join(", ", fruits);
Console.WriteLine(result);
実行結果は次のとおりです。
りんご, みかん, ぶどうリストにも使用できます。
var names = new List<string>{"田中","佐藤","鈴木"};string result = string.Join(" / ", names);
Console.WriteLine(result);
数値の配列も結合できます。
int[] numbers = { 10, 20, 30 };string result = string.Join("-", numbers);
Console.WriteLine(result); // 10-20-30
3-5. StringBuilderを使うべきケース
ループの中で文字列を繰り返し結合すると、新しい文字列オブジェクトが何度も作られます。
string result = "";for (int i = 0; i < 10000; i++){result += i;}
このような処理では、StringBuilderを使うと効率的です。
using System.Text;var builder = new StringBuilder();
for (int i = 0; i < 10000; i++){builder.Append(i);}
string result = builder.ToString();
改行付きで追加する場合は、AppendLineを使います。
var builder = new StringBuilder();builder.AppendLine("1行目");builder.AppendLine("2行目");builder.AppendLine("3行目");
Console.WriteLine(builder.ToString());
少数の文字列を1回だけ結合する処理では、無理にStringBuilderを使う必要はありません。ループ内で大量に追加する場合や、段階的に長い文字列を組み立てる場合に効果を発揮します。
4. C#で文字列を分割する方法
4-1. Splitで文字列を分割する
文字列を区切り文字ごとに分割するには、Splitメソッドを使用します。
string text = "りんご,みかん,ぶどう";string[] fruits = text.Split(',');
分割結果は文字列配列として返されます。
foreach (string fruit in fruits){Console.WriteLine(fruit);}実行結果は次のとおりです。
りんごみかんぶどう4-2. カンマ区切り・スペース区切りの文字列を分割する
カンマ区切りの文字列は、次のように分割できます。
string csv = "田中,30,東京";string[] values = csv.Split(',');Console.WriteLine(values[0]); // 田中Console.WriteLine(values[1]); // 30Console.WriteLine(values[2]); // 東京
スペース区切りの場合は、スペースを指定します。
string text = "C# Java Python";string[] languages = text.Split(' ');タブで分割する場合は、\tを指定します。
string text = "商品名\t価格\t在庫";string[] columns = text.Split('\t');ただし、一般的なCSVでは、ダブルクォートで囲まれた値の中にカンマや改行が含まれる場合があります。そのような本格的なCSVを単純なSplit(',')だけで正しく解析することはできません。実務ではCSV解析用ライブラリや適切なパーサーを利用しましょう。
4-3. 複数の区切り文字で分割する
複数の区切り文字を指定して分割できます。
string text = "りんご,みかん;ぶどう";char[] separators = { ',', ';' };string[] fruits = text.Split(separators);
カンマ、スペース、タブのいずれかで分割する例は次のとおりです。
string text = "C#,Java Python\tJavaScript";string[] languages = text.Split(new[] { ',', ' ', '\t' },StringSplitOptions.RemoveEmptyEntries);
複数文字で構成される区切り文字も指定できます。
string text = "東京--大阪##福岡";string[] cities = text.Split(new[] { "--", "##" },StringSplitOptions.None);
4-4. 空の要素を除外して分割する
連続した区切り文字があると、通常は空の要素が配列に含まれます。
string text = "A,,B,,,C";string[] values = text.Split(',');空の要素を除外するには、StringSplitOptions.RemoveEmptyEntriesを指定します。
string[] values = text.Split(',',StringSplitOptions.RemoveEmptyEntries);前後の空白も同時に取り除きたい場合は、StringSplitOptions.TrimEntriesを組み合わせます。
string text = " りんご, , みかん ,ぶどう ";string[] fruits = text.Split(',',StringSplitOptions.RemoveEmptyEntries |StringSplitOptions.TrimEntries);
この結果、配列にはりんご、みかん、ぶどうが格納されます。
4-5. 分割した文字列を配列として扱う
Splitの戻り値はstring[]です。インデックスを指定して各要素を取得できます。
string text = "田中,30,東京";string[] values = text.Split(',');string name = values[0];string age = values[1];string city = values[2];
要素数はLengthで確認できます。
Console.WriteLine(values.Length); // 3配列の範囲を超えたインデックスを指定すると例外が発生するため、事前に要素数を確認します。
if (values.Length >= 3){Console.WriteLine($"名前:{values[0]}");Console.WriteLine($"年齢:{values[1]}");Console.WriteLine($"住所:{values[2]}");}すべての要素を処理する場合は、foreachが便利です。
foreach (string value in values){Console.WriteLine(value);}5. C#で文字列を置換・削除・整形する方法
5-1. Replaceで文字列を置換する
Replaceメソッドは、指定した文字列を別の文字列に置き換えます。
string text = "私はJavaを学習しています。";string result = text.Replace("Java", "C#");
Console.WriteLine(result);
実行結果は次のとおりです。
私はC#を学習しています。同じ文字列が複数含まれている場合は、すべて置換されます。
string text = "猫と猫と猫";string result = text.Replace("猫", "犬");Console.WriteLine(result); // 犬と犬と犬
文字を削除したい場合は、置換後の文字列に空文字を指定する方法もあります。
string text = "090-1234-5678";string result = text.Replace("-", "");Console.WriteLine(result); // 09012345678
Replaceは元の文字列を変更しないため、戻り値を変数に代入してください。
5-2. Removeで指定した文字を削除する
Removeメソッドは、インデックスを指定して文字列の一部を削除します。
指定位置から末尾まで削除する例です。
string text = "ABCDE";string result = text.Remove(3);Console.WriteLine(result); // ABC
開始位置と文字数を指定することもできます。
string text = "ABCDE";string result = text.Remove(1, 2);Console.WriteLine(result); // ADE
この例では、インデックス1から2文字分のBCが削除されます。
特定の文字そのものをすべて削除したい場合は、RemoveよりReplaceのほうが簡単です。
string phoneNumber = "03-1234-5678";string result = phoneNumber.Replace("-", "");条件に一致する文字を削除する場合は、LINQを使う方法もあります。
using System.Linq;string text = "A1B2C3";string result = new string(text.Where(c => !char.IsDigit(c)).ToArray());
Console.WriteLine(result); // ABC
5-3. Trim・TrimStart・TrimEndで空白を削除する
文字列の先頭と末尾にある空白を削除するには、Trimを使用します。
string text = " C#入門 ";string result = text.Trim();Console.WriteLine($"[{result}]"); // [C#入門]
先頭だけを削除する場合は、TrimStartを使います。
string result = text.TrimStart();末尾だけを削除する場合は、TrimEndを使います。
string result = text.TrimEnd();特定の文字を削除することもできます。
string text = "---C#入門---";string result = text.Trim('-');
Console.WriteLine(result); // C#入門
複数の文字を対象にできます。
string text = "---C#入門---";string result = text.Trim('*', '-');
Console.WriteLine(result); // C#入門
Trimは文字列の途中にある空白を削除しません。
string text = " C# 入門 ";string result = text.Trim();Console.WriteLine(result); // C# 入門
5-4. ToUpper・ToLowerで大文字小文字を変換する
英字を大文字に変換するには、ToUpperを使用します。
string text = "Hello C#";string upper = text.ToUpper();Console.WriteLine(upper); // HELLO C#
小文字に変換するには、ToLowerを使用します。
string lower = text.ToLower();Console.WriteLine(lower); // hello c#
言語や地域に依存しない変換をしたい場合は、ToUpperInvariantまたはToLowerInvariantを使用します。
string normalized = text.ToLowerInvariant();識別子や設定値など、ユーザーの言語設定に左右されたくない処理では、Invariant版が適している場合があります。
ただし、文字列を比較するためだけに両方を小文字へ変換する方法は、不要な文字列生成や言語依存の問題につながることがあります。比較にはStringComparisonを指定する方法がおすすめです。
5-5. PadLeft・PadRightで桁揃えする
PadLeftは、文字列の左側に文字を追加して指定した長さにそろえます。
string number = "123";string result = number.PadLeft(5, '0');Console.WriteLine(result); // 00123
空白で右寄せする場合は、追加する文字を省略できます。
string text = "C#";string result = text.PadLeft(10);Console.WriteLine($"[{result}]");
PadRightは、右側に文字を追加します。
string text = "C#";string result = text.PadRight(5, '-');Console.WriteLine(result); // C#---
一覧表示の桁をそろえる場合に便利です。
Console.WriteLine("商品".PadRight(10) + "価格".PadLeft(8));Console.WriteLine("りんご".PadRight(10) + "120".PadLeft(8));ただし、日本語の全角文字はコンソール上の表示幅が英数字と異なることがあります。Lengthでそろえても、見た目が完全には一致しない場合があります。
6. C#で文字列を検索する方法
6-1. Containsで文字列が含まれるか判定する
Containsは、指定した文字列が含まれているかをbool値で返します。
string text = "C#の文字列操作を学習する";bool contains = text.Contains("文字列");
Console.WriteLine(contains); // True
条件分岐で使用できます。
if (text.Contains("C#")){Console.WriteLine("C#が含まれています");}大文字小文字を区別せずに検索する場合は、StringComparisonを指定します。
string text = "Hello World";bool contains = text.Contains("hello",StringComparison.OrdinalIgnoreCase);
Console.WriteLine(contains); // True
6-2. IndexOfで文字列の位置を取得する
IndexOfは、指定した文字列が最初に見つかった位置を返します。
string text = "C#の文字列操作";int index = text.IndexOf("文字列");
Console.WriteLine(index); // 3
インデックスは0から始まります。見つからなかった場合は-1が返されます。
int index = text.IndexOf("Java");if (index == -1){Console.WriteLine("見つかりませんでした");}
大文字小文字を区別せずに検索する場合は、比較方法を指定します。
string text = "Hello World";int index = text.IndexOf("world",StringComparison.OrdinalIgnoreCase);
Console.WriteLine(index); // 6
6-3. LastIndexOfで後ろから検索する
LastIndexOfは、指定した文字列が最後に現れる位置を返します。
string text = "C# Java C# Python C#";int index = text.LastIndexOf("C#");
Console.WriteLine(index);
ファイルパスから最後の区切り文字の位置を探す場合にも使用できます。
string path = @"C:\work\data\sample.txt";int index = path.LastIndexOf('\');
if (index >= 0){string fileName = path[(index + 1)..];Console.WriteLine(fileName); // sample.txt}
ファイルパスを扱う実務コードでは、文字列を直接解析するより、Path.GetFileNameなどのSystem.IO.Pathクラスを使うほうが安全です。
using System.IO;string fileName = Path.GetFileName(path);
6-4. StartsWithで先頭の文字列を判定する
StartsWithは、文字列が指定した文字列で始まるかどうかを判定します。
string url = "https://example.com";if (url.StartsWith("https://")){Console.WriteLine("HTTPSのURLです");}
大文字小文字を区別しない場合は、StringComparisonを指定します。
bool result = url.StartsWith("HTTPS://",StringComparison.OrdinalIgnoreCase);ファイル名の接頭辞や商品コードなどの判定にも利用できます。
string productCode = "ABC-001";if (productCode.StartsWith("ABC-")){Console.WriteLine("ABCシリーズです");}
6-5. EndsWithで末尾の文字列を判定する
EndsWithは、文字列が指定した文字列で終わるかどうかを判定します。
string fileName = "sample.csv";if (fileName.EndsWith(".csv")){Console.WriteLine("CSVファイルです");}
拡張子は大文字で記述される可能性もあるため、大文字小文字を区別しない比較が適しています。
bool isCsv = fileName.EndsWith(".csv",StringComparison.OrdinalIgnoreCase);ただし、ファイルの拡張子を厳密に取得する場合は、Path.GetExtensionを使用できます。
using System.IO;string extension = Path.GetExtension(fileName);
bool isCsv = string.Equals(extension,".csv",StringComparison.OrdinalIgnoreCase);
7. C#で文字列を比較する方法
7-1. ==演算子で文字列を比較する
C#では、==演算子を使って文字列の内容を比較できます。
string text1 = "C#";string text2 = "C#";bool result = text1 == text2;
Console.WriteLine(result); // True
stringの==演算子は、通常の参照型のように参照先だけを比べるのではなく、文字列の内容を比較します。
異なる文字列ならfalseです。
string text1 = "C#";string text2 = "Java";Console.WriteLine(text1 == text2); // False
null同士の比較も可能です。
string? text1 = null;string? text2 = null;Console.WriteLine(text1 == text2); // True
7-2. Equalsで文字列を比較する
Equalsメソッドでも文字列を比較できます。
string text1 = "C#";string text2 = "C#";bool result = text1.Equals(text2);
Console.WriteLine(result); // True
ただし、呼び出し元がnullの場合、インスタンスメソッドのEqualsは呼び出せません。
string? text1 = null;string text2 = "C#";// text1.Equals(text2) は例外になる可能性がある
string.Equalsという静的メソッドを使えば、nullを安全に比較できます。
bool result = string.Equals(text1, text2);比較方法も指定できます。
bool result = string.Equals("hello","HELLO",StringComparison.OrdinalIgnoreCase);Console.WriteLine(result); // True
7-3. Compare・CompareToで大小関係を比較する
string.Compareは、2つの文字列の並び順を比較します。
int result = string.Compare("Apple", "Banana");戻り値の意味は次のとおりです。
| 戻り値 | 意味 |
| 0未満 | 1つ目の文字列が前 |
| 0 | 2つの文字列が等しい |
| 0より大きい | 1つ目の文字列が後 |
次のように条件分岐できます。
int result = string.Compare("Apple","Banana",StringComparison.Ordinal);if (result < 0){Console.WriteLine("Appleが先です");}else if (result > 0){Console.WriteLine("Bananaが先です");}else{Console.WriteLine("同じ文字列です");}
CompareToも大小関係を比較します。
string text = "Apple";int result = text.CompareTo("Banana");ただし、比較ルールを明示したい場合は、StringComparisonを指定できるstring.Compareのほうが意図を表しやすくなります。
7-4. 大文字小文字を区別せずに比較する
通常の比較では、大文字と小文字は異なる文字として扱われます。
Console.WriteLine("hello" == "HELLO"); // False大文字小文字を無視するには、StringComparison.OrdinalIgnoreCaseなどを指定します。
bool result = string.Equals("hello","HELLO",StringComparison.OrdinalIgnoreCase);Console.WriteLine(result); // True
次のように両方を小文字へ変換して比較する方法もありますが、一般には推奨されません。
bool result = text1.ToLower() == text2.ToLower();この方法では新しい文字列が作られるほか、言語や地域による変換ルールの影響を受ける可能性があります。比較用のAPIにStringComparisonを指定するほうが明確です。
7-5. StringComparisonを指定して安全に比較する
StringComparisonを指定すると、文字列をどのルールで比較するか明示できます。
代表的な値は次のとおりです。
| 値 | 特徴 |
Ordinal | UTF-16コード単位に基づいて比較する |
OrdinalIgnoreCase | 大文字小文字を無視してコード単位で比較する |
CurrentCulture | 現在のカルチャに基づいて比較する |
CurrentCultureIgnoreCase | 現在のカルチャに基づき、大文字小文字を無視する |
InvariantCulture | 言語に依存しにくいカルチャ規則で比較する |
InvariantCultureIgnoreCase | 言語に依存しにくい規則で大文字小文字を無視する |
ユーザーに表示する自然言語の並べ替えでは、カルチャに基づく比較が適している場合があります。
一方、ファイル拡張子、プロトコル名、内部コード、識別子などを比較する場合は、OrdinalまたはOrdinalIgnoreCaseがよく使われます。
bool isAdmin = string.Equals(role,"ADMIN",StringComparison.OrdinalIgnoreCase);比較方法を明示すると、実行環境による意図しない結果を防ぎやすくなります。
8. C#で文字列の一部を取得する方法
8-1. Substringで指定範囲の文字列を取り出す
Substringを使うと、指定した位置から文字列を取り出せます。
string text = "ABCDE";string result = text.Substring(2);
Console.WriteLine(result); // CDE
開始位置と文字数を指定することもできます。
string result = text.Substring(1, 3);Console.WriteLine(result); // BCD
Substring(1, 3)は、インデックス1から3文字を取得するという意味です。
8-2. インデックスは0から始まる点に注意する
C#の文字列インデックスは0から始まります。
文字 A B C D Eインデックス 0 1 2 3 4最初の文字はインデックス0です。
string text = "ABCDE";char first = text[0];
Console.WriteLine(first); // A
3文字目を取得する場合は、インデックス2を指定します。
char third = text[2];Console.WriteLine(third); // C
text[text.Length]は範囲外です。最後の文字を取得する場合は、text.Length - 1を指定します。
char last = text[text.Length - 1];ただし、空文字ではtext.Length - 1が負の値になるため、事前に確認が必要です。
8-3. 範囲演算子で文字列を切り出す
C# 8以降では、範囲演算子..を使って文字列を切り出せます。
string text = "ABCDE";string result = text[1..4];
Console.WriteLine(result); // BCD
開始位置は含まれ、終了位置は含まれません。
開始位置を省略すると、先頭から取得します。
string result = text[..3];Console.WriteLine(result); // ABC
終了位置を省略すると、指定位置から末尾まで取得します。
string result = text[2..];Console.WriteLine(result); // CDE
Substringよりも簡潔に書けますが、インデックスが範囲外になると例外が発生する点は同じです。
8-4. 先頭・末尾から文字列を取得する
先頭から3文字を取得する例です。
string text = "ABCDE";string firstThree = text[..3];
Console.WriteLine(firstThree); // ABC
末尾から数える場合は、^演算子を使用します。
char last = text[^1];Console.WriteLine(last); // E
^1は末尾から1番目、^2は末尾から2番目を表します。
末尾3文字を取得する場合は、次のように記述します。
string lastThree = text[^3..];Console.WriteLine(lastThree); // CDE
先頭と末尾を除いた部分を取得することもできます。
string middle = text[1..^1];Console.WriteLine(middle); // BCD
8-5. 範囲外エラーを防ぐためのチェック方法
文字列の長さを超えた範囲を指定すると、ArgumentOutOfRangeExceptionが発生します。
string text = "ABC";string result = text.Substring(0, 10);取得前に長さを確認します。
string text = "ABC";int count = 10;if (text.Length >= count){string result = text[..count];Console.WriteLine(result);}
指定文字数まで取得し、短い場合は全文を取得するなら、Math.Minを使えます。
string text = "ABC";int maxLength = 10;string result = text[..Math.Min(text.Length, maxLength)];
Console.WriteLine(result); // ABC
先頭から最大10文字を取得する処理としてメソッド化すると、再利用しやすくなります。
static string TakeStart(string text, int maxLength){if (text is null){throw new ArgumentNullException(nameof(text));}if (maxLength < 0){throw new ArgumentOutOfRangeException(nameof(maxLength));}return text<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[..Math.Min(text.Length, maxLength)]</span>;
}
9. C#で文字列を変換する方法
9-1. 数値を文字列に変換する
数値を文字列に変換する基本的な方法は、ToStringです。
int number = 123;string text = number.ToString();Console.WriteLine(text);
書式も指定できます。
int number = 1234567;string text = number.ToString("N0");
Console.WriteLine(text);
一般的な日本語環境では、次のように表示されます。
1,234,567ゼロ埋めもできます。
int number = 123;string text = number.ToString("D5");
Console.WriteLine(text); // 00123
文字列補間でも変換できます。
decimal price = 1980.5m;string message = $"価格は{price:N0}円です。";
9-2. 文字列をintやdoubleに変換する
文字列をintへ変換するには、int.Parseを使用します。
string text = "123";int number = int.Parse(text);Console.WriteLine(number + 1); // 124
doubleへ変換する場合は、double.Parseを使用します。
string text = "12.5";double number = double.Parse(text);Console.WriteLine(number);
ただし、変換できない文字列を指定すると例外が発生します。
string text = "abc";int number = int.Parse(text); // FormatExceptionユーザー入力など、内容が保証されていない文字列にはTryParseを使うほうが安全です。
9-3. ParseとTryParseの違い
Parseは変換に失敗すると例外を発生させます。
int number = int.Parse("123");TryParseは、変換に成功したかどうかをboolで返します。
string input = "123";if (int.TryParse(input, out int number)){Console.WriteLine($"変換成功:{number}");}else{Console.WriteLine("整数として解釈できません");}
変換に失敗しても、通常は例外が発生しません。
string input = "abc";bool success = int.TryParse(input, out int number);
Console.WriteLine(success); // FalseConsole.WriteLine(number); // 0
ユーザー入力、CSV、外部APIなど、正しい形式とは限らないデータを扱う場合は、TryParseが適しています。
9-4. 日付文字列をDateTimeに変換する
日付文字列は、DateTime.Parseで変換できます。
string text = "2026-06-20";DateTime date = DateTime.Parse(text);Console.WriteLine(date);
変換できるか安全に確認するには、DateTime.TryParseを使用します。
string input = "2026-06-20";if (DateTime.TryParse(input, out DateTime date)){Console.WriteLine(date.ToString("yyyy年MM月dd日"));}else{Console.WriteLine("日付の形式が正しくありません");}
入力形式を厳密に指定したい場合は、DateTime.TryParseExactを使います。
using System.Globalization;string input = "2026/06/20";
bool success = DateTime.TryParseExact(input,"yyyy/MM/dd",CultureInfo.InvariantCulture,DateTimeStyles.None,out DateTime date);
if (success){Console.WriteLine(date);}
複数の形式を許可することもできます。
string[] formats ={"yyyy/MM/dd","yyyy-MM-dd","yyyyMMdd"};bool success = DateTime.TryParseExact(input,formats,CultureInfo.InvariantCulture,DateTimeStyles.None,out DateTime date);
9-5. 変換エラーを防ぐ実装例
年齢の入力値を安全に変換する例です。
Console.Write("年齢を入力してください:");string? input = Console.ReadLine();if (int.TryParse(input, out int age) && age >= 0 && age <= 150){Console.WriteLine($"入力された年齢は{age}歳です。");}else{Console.WriteLine("0から150までの整数を入力してください。");}
金額を変換する場合は、小数点や桁区切りの扱いを明示すると安全です。
using System.Globalization;string input = "1,980.50";
bool success = decimal.TryParse(input,NumberStyles.Number,CultureInfo.InvariantCulture,out decimal price);
if (success){Console.WriteLine(price);}
変換できるかどうかだけでなく、変換後の値が許容範囲内かも確認することが重要です。
10. C#の文字列操作でよくあるエラーと対策
10-1. NullReferenceExceptionが発生する原因
文字列変数がnullの状態で、LengthやTrimなどを呼び出すとNullReferenceExceptionが発生します。
string? text = null;Console.WriteLine(text.Length);
事前にnullを確認します。
if (text is not null){Console.WriteLine(text.Length);}null条件演算子も使用できます。
int length = text?.Length ?? 0;nullまたは空文字をまとめて判定するなら、string.IsNullOrEmptyが便利です。
if (string.IsNullOrEmpty(text)){Console.WriteLine("文字列がありません");}空白だけの文字列も無効としたい場合は、string.IsNullOrWhiteSpaceを使用します。
if (string.IsNullOrWhiteSpace(text)){Console.WriteLine("有効な文字が入力されていません");}10-2. IndexOutOfRangeExceptionを防ぐ方法
存在しないインデックスで文字を取得すると、IndexOutOfRangeExceptionが発生します。
string text = "ABC";char value = text[3];
ABCの有効なインデックスは0から2です。取得前にLengthを確認します。
int index = 3;if (index >= 0 && index < text.Length){char value = text[index];}
空文字から先頭の文字を取得しようとした場合も例外になります。
string text = "";if (text.Length > 0){Console.WriteLine(text[0]);}
Split後の配列をインデックスで参照するときも、要素数を確認してください。
string[] values = input.Split(',');if (values.Length >= 3){Console.WriteLine(values[2]);}
10-3. 文字列比較で意図しない結果になる原因
大文字小文字やカルチャの違いにより、期待した比較結果にならないことがあります。
Console.WriteLine("admin" == "ADMIN"); // False大文字小文字を無視するなら、比較方法を指定します。
bool result = string.Equals("admin","ADMIN",StringComparison.OrdinalIgnoreCase);前後に空白が含まれている可能性もあります。
string input = " admin ";bool result = string.Equals(input.Trim(),"admin",StringComparison.OrdinalIgnoreCase);
ただし、入力データを無条件にTrimしてよいかは、要件に応じて判断してください。パスワードなど、空白自体が意味を持つデータを勝手に加工してはいけません。
10-4. 日本語や全角文字を扱うときの注意点
半角文字と全角文字は、通常は異なる文字として扱われます。
string text1 = "ABC";string text2 = "ABC";Console.WriteLine(text1 == text2); // False
半角スペースと全角スペースも異なります。
string halfWidth = " ";string fullWidth = " ";Console.WriteLine(halfWidth == fullWidth); // False
見た目が似ている文字でも、Unicode上の表現が異なる場合があります。比較前に正規化が必要な要件では、Normalizeを利用できます。
using System.Text;string normalized1 = text1.Normalize(NormalizationForm.FormC);string normalized2 = text2.Normalize(NormalizationForm.FormC);
bool result = normalized1 == normalized2;
ただし、Unicode正規化だけでは半角英数字を全角英数字へ統一するような、すべての表記ゆれを解消できるわけではありません。どの表記を同一とみなすか、システムの要件を明確にする必要があります。
また、絵文字などはUTF-16上で複数のcharから構成されることがあります。
string emoji = "😀";Console.WriteLine(emoji.Length); // 2
見た目上の文字を単純に1文字ずつ処理したい場合、char単位のループでは不十分なことがあります。用途に応じてSystem.Text.Runeやテキスト要素単位の処理を検討しましょう。
10-5. ループ内の文字列結合で処理が遅くなる原因
stringはイミュータブルなので、+=で結合するたびに新しい文字列が作られます。
string result = "";for (int i = 0; i < 10000; i++){result += i + ",";}
繰り返し回数が多い場合、メモリ確保とコピーが増え、処理が遅くなる可能性があります。
StringBuilderを使用すると、内部バッファーへ効率よく追加できます。
using System.Text;var builder = new StringBuilder();
for (int i = 0; i < 10000; i++){if (i > 0){builder.Append(',');}
builder.Append(i);
}
string result = builder.ToString();
配列やリストの要素を区切り文字付きで結合するだけなら、StringBuilderを自分で記述するよりstring.Joinのほうが簡潔です。
string result = string.Join(",", numbers);11. C#文字列操作の実践サンプル
11-1. 入力された文字列が空か判定する
ユーザー入力がnull、空文字、空白だけの文字列かを判定します。
Console.Write("名前を入力してください:");string? input = Console.ReadLine();if (string.IsNullOrWhiteSpace(input)){Console.WriteLine("名前が入力されていません。");}else{string name = input.Trim();Console.WriteLine($"こんにちは、{name}さん。");}
string.IsNullOrWhiteSpaceは、次のような値をすべてtrueと判定します。
string? value1 = null;string value2 = "";string value3 = " ";string value4 = "\t";string value5 = "\n";必須入力のチェックに便利ですが、空白を有効な値として扱う要件には適していません。
11-2. CSV形式の文字列を分割して処理する
単純なカンマ区切りデータを分割する例です。
string line = "田中,30,東京";string[] columns = line.Split(',',StringSplitOptions.TrimEntries);
if (columns.Length == 3){string name = columns[0];string ageText = columns[1];string city = columns[2];
if (int.TryParse(ageText, out int age)){Console.WriteLine($"名前:{name}");Console.WriteLine($"年齢:{age}");Console.WriteLine($"住所:{city}");}else{Console.WriteLine("年齢の形式が正しくありません。");}
}else{Console.WriteLine("列数が正しくありません。");}
次のように引用符内にカンマを含むCSVは、単純なSplitでは正しく処理できません。
田中,30,"東京都新宿区,西新宿"実務で一般的なCSVファイルを扱う場合は、引用符、改行、エスケープなどに対応したCSVパーサーを使用してください。
11-3. 不要な空白を削除して整形する
文字列の前後にある空白を削除するだけなら、Trimを使います。
string input = " C#の文字列操作 ";string result = input.Trim();Console.WriteLine(result);
単語間に連続する空白があり、それを1つにまとめる例です。
string input = "C# の 文字列操作";string[] words = input.Split(' ',StringSplitOptions.RemoveEmptyEntries);
string result = string.Join(" ", words);
Console.WriteLine(result); // C# の 文字列操作
スペース、タブ、改行などの空白文字をまとめて処理する場合は、正規表現を利用できます。
using System.Text.RegularExpressions;string input = "C# の\t文字列\n操作";
string result = Regex.Replace(input.Trim(),@"\s+"," ");
Console.WriteLine(result); // C# の 文字列 操作
正規表現は強力ですが、単純な前後の空白削除であればTrimのほうが読みやすく効率的です。
11-4. 特定の文字列を検索して置換する
文章に特定の単語が含まれているか確認し、含まれていれば置換します。
string text = "Javaの文字列操作を学習します。";if (text.Contains("Java", StringComparison.Ordinal)){text = text.Replace("Java", "C#");}
Console.WriteLine(text);
大文字小文字を無視して置換したい場合、対応するオーバーロードを利用できる環境では、比較方法を指定できます。
string text = "Hello HELLO hello";string result = text.Replace("hello","Hi",StringComparison.OrdinalIgnoreCase);
Console.WriteLine(result); // Hi Hi Hi
置換前の文字列が空文字の場合など、入力条件も必要に応じて確認しましょう。
static string SafeReplace(string source,string oldValue,string newValue){ArgumentNullException.ThrowIfNull(source);ArgumentException.ThrowIfNullOrEmpty(oldValue);ArgumentNullException.ThrowIfNull(newValue);return source.Replace(oldValue, newValue);
}
11-5. ユーザー名やメールアドレスを簡易チェックする
ユーザー名の長さと使用可能文字を簡易チェックする例です。
using System.Text.RegularExpressions;static bool IsValidUserName(string? userName){if (string.IsNullOrWhiteSpace(userName)){return false;}
return Regex.IsMatch(userName,@"^<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[a-zA-Z0-9_]</span>{3,20}$");
}
使用例は次のとおりです。
string? userName = "taro_123";if (IsValidUserName(userName)){Console.WriteLine("使用可能なユーザー名です。");}else{Console.WriteLine("ユーザー名は3~20文字の英数字またはアンダースコアで入力してください。");}
メールアドレスを簡易チェックする場合は、MailAddressを利用できます。
using System.Net.Mail;static bool IsValidEmail(string? email){if (string.IsNullOrWhiteSpace(email)){return false;}
try{var address = new MailAddress(email);return address.Address == email;}catch (FormatException){return false;}
}
ただし、文字列の形式を確認できても、そのメールアドレスが実際に存在することまでは判定できません。ユーザー登録では確認メールを送信し、所有者本人が認証する仕組みを組み合わせる必要があります。
12. C#の文字列操作に関するよくある質問
12-1. stringとStringはどちらを使うべき?
stringとStringは、どちらもSystem.String型を表します。動作上の違いはありません。
一般的なC#コードでは、型を記述するときにC#キーワードであるstringを使います。
string name = "田中";静的メソッドも次のように呼び出せます。
bool isEmpty = string.IsNullOrEmpty(name);既存プロジェクトにコーディング規約がある場合は、その規約に従って表記を統一してください。
12-2. 文字列がnullまたは空か判定するには?
string.IsNullOrEmptyを使用します。
if (string.IsNullOrEmpty(value)){Console.WriteLine("nullまたは空文字です");}空白だけの文字列も無効とする場合は、string.IsNullOrWhiteSpaceを使用します。
if (string.IsNullOrWhiteSpace(value)){Console.WriteLine("null、空文字、または空白だけの文字列です");}入力フォームの必須チェックでは、IsNullOrWhiteSpaceが適しているケースが多くあります。
12-3. 文字列を1文字ずつ処理するには?
foreachで文字列を繰り返すと、各文字をchar型として取得できます。
string text = "C#入門";foreach (char c in text){Console.WriteLine(c);}
インデックスを使う方法もあります。
for (int i = 0; i < text.Length; i++){Console.WriteLine($"インデックス{i}:{text[i]}");}ただし、charはUTF-16コード単位を表します。絵文字など、1つの見た目の文字が複数のcharから構成される場合があります。
Unicodeのコードポイント単位で処理する場合は、EnumerateRunesを使用できます。
using System.Text;string text = "A😀B";
foreach (Rune rune in text.EnumerateRunes()){Console.WriteLine(rune);}
12-4. 文字列の比較で大文字小文字を無視するには?
string.EqualsにStringComparison.OrdinalIgnoreCaseを指定します。
bool result = string.Equals(text1,text2,StringComparison.OrdinalIgnoreCase);検索の場合も比較方法を指定できます。
bool contains = text.Contains(keyword,StringComparison.OrdinalIgnoreCase);先頭や末尾の判定にも利用できます。
bool startsWith = text.StartsWith(prefix,StringComparison.OrdinalIgnoreCase);bool endsWith = text.EndsWith(suffix,StringComparison.OrdinalIgnoreCase);
比較のためにToLowerやToUpperで変換するより、StringComparisonを直接指定する方法がおすすめです。
12-5. 文字列結合でStringBuilderを使うべきタイミングは?
少数の文字列を1回だけ結合する場合は、+演算子や文字列補間で十分です。
string message = $"{name}さん、こんにちは。";配列やリストの要素を区切り文字付きで結合する場合は、string.Joinが適しています。
string result = string.Join(",", values);StringBuilderが効果的なのは、主に次のようなケースです。
ループ内で何度も文字列を追加する
長い文章やHTML、CSVデータを段階的に組み立てる
条件に応じて文字列の追加や削除を繰り返す
大量のデータを1つの文字列へまとめる
using System.Text;var builder = new StringBuilder();
foreach (string item in items){builder.AppendLine(item);}
string result = builder.ToString();
処理回数が少ない場合は、可読性を優先して単純な方法を選びましょう。
まとめ
C#の文字列はstring型で扱い、標準メソッドを利用することでさまざまな操作を実装できます。
文字列の結合には+演算子、文字列補間、string.Joinなどを使用できます。ループ内で大量に結合するときは、StringBuilderが有効です。
分割にはSplit、置換にはReplace、前後の空白削除にはTrimを使用します。文字列の検索にはContainsやIndexOf、先頭と末尾の判定にはStartsWithとEndsWithが便利です。
文字列比較では、大文字小文字や言語設定による違いに注意し、目的に合ったStringComparisonを指定することが重要です。また、nullの可能性がある文字列には、string.IsNullOrEmptyやstring.IsNullOrWhiteSpaceを利用すると安全に判定できます。
文字列から数値や日付へ変換するときは、入力内容が保証されていない限り、例外を発生させるParseよりもTryParseを使うと安定したプログラムを作れます。
まずは、結合・分割・置換・検索・比較という基本操作を実際にコードで試し、それぞれの戻り値や例外が発生する条件を確認してみましょう。

