C#: 文字列

1. 宣言と初期化

stringSystem.String の別名であり、不変の参照型です。一度作成されると、文字列の内容を変更することはできません。

▶ サンプル

CSHARP
string name = "Hello";
string empty = "";
string nullStr = null;
string fromChar = new string('A', 5);
Console.WriteLine(name);
Console.WriteLine(fromChar);
▶ 試してみよう
TEXT 📖 参照専用
Hello
AAAAA

2. 文字列の不変性

文字列オブジェクトが一度作成されると、その文字列は変更できなくなります。すべての「変更」操作は新しい文字列を返し、元の文字列は変更されません。

▶ サンプル

CSHARP
string a = "Hello";
string b = a;
a = a + " World";
Console.WriteLine(a);
Console.WriteLine(b);
▶ 試してみよう
TEXT 📖 参照専用
Hello World
Hello

ヒント:b は依然として元の "Hello" を指していますが、a + " World" はまったく新しい文字列オブジェクトを生成します。


3. 文字列の連結

複数の文字列を結合するには、演算子 +String.Concat()、または String.Join() を使用します。

▶ サンプル

CSHARP
string s1 = "Hello" + " " + "World";
string s2 = String.Concat("A", "B", "C");
string s3 = String.Join(", ", new string[] { "apple", "banana", "cherry" });
Console.WriteLine(s1);
Console.WriteLine(s2);
Console.WriteLine(s3);
▶ 試してみよう
TEXT 📖 参照専用
Hello World
ABC
apple, banana, cherry

4. 文字列補間

文字列内に変数を埋め込むには、$"" 補間構文または String.Format() を使用してください。

▶ サンプル

CSHARP
string name = "Alice";
int age = 25;
string s1 = $"My name is {name}, age {age}.";
string s2 = String.Format("My name is {0}, age {1}.", name, age);
string s3 = $"2 + 3 = {2 + 3}";
Console.WriteLine(s1);
Console.WriteLine(s2);
Console.WriteLine(s3);
▶ 試してみよう
TEXT 📖 参照専用
My name is Alice, age 25.
My name is Alice, age 25.
2 + 3 = 5

ヒント:補間中括弧 {} 内には、任意の C# 式を記述でき、{value:F2} などのフォーマット指定子を追加することもできます。


5. 文字列の比較

== 演算子は、文字列の値の等価比較(参照比較ではない)を行います。Equals()Compare()、および CompareOrdinal() を使用すると、よりきめ細かな制御が可能です。

▶ サンプル

CSHARP
string a = "hello";
string b = "hello";
string c = "HELLO";
Console.WriteLine(a == b);
Console.WriteLine(a.Equals(b));
Console.WriteLine(String.Compare(a, c, StringComparison.OrdinalIgnoreCase) == 0);
Console.WriteLine(String.CompareOrdinal(a, c) > 0);
▶ 試してみよう
TEXT 📖 参照専用
True
True
True
True

警告:文字列 == は参照ではなく値を比較します。これは、他のほとんどの参照型の挙動とは異なります。


6. よく使われるメソッド:length / substring / replace / split

これらは、日常的な文字列操作で最も頻繁に使用されるメソッドです。

▶ サンプル

CSHARP
string s = "Hello, World!";
Console.WriteLine(s.Length);
Console.WriteLine(s.Substring(7));
Console.WriteLine(s.Substring(0, 5));
Console.WriteLine(s.Replace("World", "C#"));
string parts = "a,b,c";
foreach (string p in parts.Split(','))
{
    Console.WriteLine(p);
}
▶ 試してみよう
TEXT 📖 参照専用
13
World!
Hello
Hello, C#!
a
b
c

7. 一般的なメソッド:Trim / Contains / Index

Trim() は先頭と末尾の空白を削除し、Contains() は部分文字列の有無を確認し、IndexOf() および LastIndexOf() は位置を検索します。

▶ サンプル

CSHARP
string s = "  Hello World  ";
Console.WriteLine($"[{s.Trim()}]");
Console.WriteLine(s.Contains("World"));
Console.WriteLine(s.IndexOf("World"));
Console.WriteLine(s.LastIndexOf("o"));
▶ 試してみよう
TEXT 📖 参照専用
[Hello World]
True
8
7

8. 一般的なメソッド:Case / StartsWith / EndsWith / Pad / Remove / Insert

より実用的な文字列処理の方法。

▶ サンプル

CSHARP
string s = "Hello";
Console.WriteLine(s.ToUpper());
Console.WriteLine(s.ToLower());
Console.WriteLine(s.StartsWith("Hel"));
Console.WriteLine(s.EndsWith("llo"));
Console.WriteLine("5".PadLeft(3, '0'));
Console.WriteLine("5".PadRight(3, '0'));
string r = "Hello World".Remove(5);
Console.WriteLine(r);
string ins = "H World".Insert(1, "ello");
Console.WriteLine(ins);
▶ 試してみよう
TEXT 📖 参照専用
HELLO
hello
True
True
005
500
Hello
Hello World

9. バーバティム文字列と生文字列

リテラル文字列 @"" はエスケープシーケンスを処理しないため、ファイルパスの指定に最適です。C# 11 では、エスケープ処理を必要としない複数行のコンテンツ向けに、生文字列リテラル """ が導入されました。

▶ サンプル

CSHARP
string path = @"C:\Users\Doc\file.txt";
string json = """
    {
        "name": "Alice",
        "age": 25
    }
    """;
Console.WriteLine(path);
Console.WriteLine(json.Trim());
▶ 試してみよう
TEXT 📖 参照専用
C:\Users\Doc\file.txt
{
    "name": "Alice",
    "age": 25
}

ヒント:逐語文字列では、二重引用符は "" と記述されます。生文字列リテラルは、少なくとも3つの引用符で始まり、3つの引用符で終わります。


10. StringBuilder の概要

ループ内で文字列を繰り返し連結する場合、string はその都度新しいオブジェクトを作成するため、パフォーマンスが低下します。一方、StringBuilder は内部バッファ上で処理を行い、最終的な文字列を一度だけ生成します。

▶ サンプル

CSHARP
using System.Text;

var sb = new StringBuilder();
for (int i = 0; i < 5; i++)
{
    sb.Append(i);
    sb.Append(" ");
}
Console.WriteLine(sb.ToString().Trim());
▶ 試してみよう
TEXT 📖 参照専用
0 1 2 3 4

ヒント:ループ内で多数の文字列を連結する際は、StringBuilder を使用すると、メモリの割り当てを大幅に削減できます。


11. 文字エンコーディング

C#の文字列はUTF-16エンコーディングを使用します。charは2バイト(1つのUTF-16コード単位)を占めます。

▶ サンプル

CSHARP
char ch = 'A';
Console.WriteLine(ch);
Console.WriteLine((int)ch);
Console.WriteLine(sizeof(char));
▶ 試してみよう
TEXT 📖 参照専用
A
65
2

❓ よくある質問

Q 文字列 == は参照を比較するのか、それとも値を比較するのか?
A 値を比較します。文字列用の == 演算子は、内容による等価比較を行うようにオーバーロードされています。
Q ループ内で文字列を連結する際、なぜStringBuilderを使うべきなのでしょうか?
A stringは不変であるため、連結を行うたびに新しいオブジェクトが生成されてしまいます。一方、StringBuilderはバッファを修正し、最後にのみ最終的な文字列を生成します。
Q リテラル文字列 @"" と通常の文字列の違いは何ですか?
A リテラル文字列では、エスケープシーケンス(\n\t など)は処理されません。 バックスラッシュは文字通りそのまま保持されるため、ファイルパスや正規表現に最適です。
Q Substring の範囲外を指定した場合はどうなりますか?
A ArgumentOutOfRangeException が発生します。呼び出す前に長さを確認してください。

📖 まとめ

📝 練習問題

  1. 文字列変数を宣言し、補間を使用して "My name is XXX, and I am XX years old." を出力する
  2. カンマ区切りの文字列 "a,b,c,d" を受け取り、Split で分割し、各要素を別々の行に出力するプログラムを作成してください。
  3. 文字列 " Hello World " を切り取り、"World""C#" に置き換えて、その結果を出力してください
  4. StringBuilder を使用して、1 から 100 までの数字を 1 行に 1 つずつ連結し、最終的な文字列を出力してください
  5. 文字列リテラルを使用して Windows ファイルパス C:\Program Files\MyApp\config.json を定義し、それを出力する
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%