C#のstring.Join完全ガイド|配列・リストを区切り文字で結合する使い方と実例

はじめに

C#で配列やリストの要素を1つの文字列にまとめたいときは、string.Joinを使うのが定番です。

たとえば、次のような場面です。

C#
var names = new[] { "Alice", "Bob", "Charlie" };

string result = string.Join(", ", names);

Console.WriteLine(result);

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

Alice, Bob, Charlie

string.Joinを使うと、配列・List<string>List<int>・LINQの結果などを、カンマ区切り、スペース区切り、改行区切りなどの文字列に簡単に変換できます。

この記事では、C#のstring.Joinについて、基本構文から配列・リストでの使い方、nullや空文字の扱い、よくあるエラー、実務で使えるサンプルまで詳しく解説します。

1. C#のstring.Joinとは?配列・リストを区切り文字で結合する基本

1-1. string.Joinでできること

string.Joinは、複数の要素を指定した区切り文字でつなげて、1つの文字列にするメソッドです。

たとえば、配列の中身をカンマ区切りで結合できます。

C#
string[] fruits = { "Apple", "Banana", "Orange" };

string result = string.Join(", ", fruits);

Console.WriteLine(result);

実行結果は次のとおりです。

Apple, Banana, Orange

このように、string.Joinを使うと、要素と要素の間にだけ区切り文字を入れて文字列を作れます。

重要なのは、最後の要素の後ろには区切り文字が付かないことです。

C#
string[] values = { "A", "B", "C" };

Console.WriteLine(string.Join(",", values));

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

A,B,C

A,B,C,のように、末尾に余計なカンマは付きません。

1-2. 「c# join string」で検索する人が知りたい結論

C#で文字列を結合したい場合、目的によって使うメソッドが変わります。

配列やリストを区切り文字付きで結合したいなら、基本的にはstring.Joinを使います。

C#
var list = new List<string> { "red", "green", "blue" };

string result = string.Join(" / ", list);

Console.WriteLine(result);

実行結果は次のとおりです。

red / green / blue

つまり、「c# join string」で検索している人がまず覚えるべき結論は次のとおりです。

配列やリストをカンマ区切りなどで1つの文字列にしたい場合は、string.Join(区切り文字, 結合対象)を使います。

C#
string result = string.Join(", ", values);

この形を覚えておけば、多くのケースに対応できます。

1-3. string.Joinを使うべきケース

string.Joinは、複数の値を区切り文字付きで表示・出力したいときに向いています。

代表的なケースは次のようなものです。

C#
string[] names = { "田中", "佐藤", "鈴木" };

string displayText = string.Join("、", names);

Console.WriteLine(displayText);

実行結果は次のとおりです。

田中、佐藤、鈴木

ログ出力にもよく使われます。

C#
int[] ids = { 101, 102, 103 };

Console.WriteLine($"対象ID: {string.Join(", ", ids)}");

実行結果は次のとおりです。

対象ID: 101, 102, 103

エラーメッセージを改行区切りで表示する場合にも便利です。

C#
var errors = new List<string>
{
"名前を入力してください。",
"メールアドレスを入力してください。",
"パスワードは8文字以上にしてください。"
};

string message = string.Join(Environment.NewLine, errors);

Console.WriteLine(message);

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

名前を入力してください。
メールアドレスを入力してください。
パスワードは8文字以上にしてください。

string.Joinは、次のような場面で特に便利です。

配列の中身を表示したいとき、リストをカンマ区切りにしたいとき、ログに複数の値を出したいとき、画面表示用の文字列を作りたいとき、改行区切りのメッセージを作りたいときなどです。

1-4. 文字列連結の「+」「StringBuilder」「Concat」との違い

C#には文字列を結合する方法が複数あります。

たとえば、+演算子を使う方法です。

C#
string firstName = "Taro";
string lastName = "Yamada";

string fullName = lastName + " " + firstName;

Console.WriteLine(fullName);

実行結果は次のとおりです。

Yamada Taro

+は、少数の文字列を直接つなげる場合に読みやすいです。

一方で、配列やリストの要素を区切り文字付きで結合する場合は、+よりもstring.Joinのほうが適しています。

C#
var items = new[] { "A", "B", "C" };

string result = string.Join(",", items);

StringBuilderは、ループの中で何度も文字列を追加していくような処理に向いています。

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

builder.Append("Hello");
builder.Append(" ");
builder.Append("World");

string result = builder.ToString();

Console.WriteLine(result);

実行結果は次のとおりです。

Hello World

string.Concatは、区切り文字を入れずに文字列を連結するメソッドです。

C#
string[] values = { "A", "B", "C" };

string result = string.Concat(values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

違いをまとめると、次のようになります。

C#
string[] values = { "A", "B", "C" };

Console.WriteLine(string.Join(",", values)); // A,B,C
Console.WriteLine(string.Concat(values)); // ABC

区切り文字を入れたいならstring.Join、区切り文字なしで単純につなげたいならstring.Concat、少数の文字列なら+や文字列補間、複雑な組み立てならStringBuilderを使うと考えると分かりやすいです。

2. string.Joinの基本構文と引数の意味

2-1. 基本構文:string.Join(区切り文字, 結合対象)

string.Joinの基本構文は次のとおりです。

C#
string result = string.Join(区切り文字, 結合対象);

実際のコードでは、次のように書きます。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

第1引数には区切り文字を指定します。

第2引数には、結合したい配列やリストを指定します。

C#
var numbers = new List<int> { 1, 2, 3 };

string result = string.Join(" - ", numbers);

Console.WriteLine(result);

実行結果は次のとおりです。

1 - 2 - 3

string.Joinは、文字列配列だけでなく、数値のリストなどにも使えます。

2-2. 第1引数:区切り文字の指定方法

第1引数には、要素と要素の間に入れる文字列を指定します。

カンマ区切りにする場合は、次のように書きます。

C#
string result = string.Join(",", values);

カンマの後にスペースを入れたい場合は、次のようにします。

C#
string result = string.Join(", ", values);

スペース区切りにする場合は、次のように書きます。

C#
string result = string.Join(" ", values);

改行区切りにする場合は、Environment.NewLineを使うと環境に合った改行コードを使えます。

C#
string result = string.Join(Environment.NewLine, values);

スラッシュ区切りも可能です。

C#
string result = string.Join("/", values);

区切り文字には、任意の文字列を指定できます。

C#
string[] words = { "C#", "Java", "Python" };

Console.WriteLine(string.Join(" | ", words));

実行結果は次のとおりです。

C# | Java | Python

2-3. 第2引数:配列・List・IEnumerableの指定方法

第2引数には、結合したい要素の集合を指定します。

文字列配列を渡す例です。

C#
string[] names = { "Alice", "Bob", "Charlie" };

string result = string.Join(", ", names);

List<string>を渡す例です。

C#
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };

string result = string.Join(", ", names);

List<int>のような数値リストも渡せます。

C#
List<int> scores = new List<int> { 80, 90, 100 };

string result = string.Join(", ", scores);

Console.WriteLine(result);

実行結果は次のとおりです。

80, 90, 100

LINQの結果も渡せます。

C#
var users = new List<string> { "alice", "bob", "charlie" };

string result = string.Join(", ", users.Select(x => x.ToUpper()));

Console.WriteLine(result);

実行結果は次のとおりです。

ALICE, BOB, CHARLIE

このように、string.JoinIEnumerable<T>を扱えるため、配列・リスト・LINQの結果と相性がよいです。

2-4. 戻り値として返される文字列

string.Joinは、結合した結果を新しい文字列として返します。

元の配列やリストが変更されるわけではありません。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

Console.WriteLine(result);
Console.WriteLine(values[0]);

実行結果は次のとおりです。

A,B,C
A

string.Joinの戻り値はstring型です。

そのため、変数に代入したり、Console.WriteLineに直接渡したり、文字列補間の中で使ったりできます。

C#
var ids = new[] { 10, 20, 30 };

Console.WriteLine($"ID一覧: {string.Join(", ", ids)}");

実行結果は次のとおりです。

ID一覧: 10, 20, 30

2-5. よく使うオーバーロード一覧

string.Joinには複数のオーバーロードがあります。

よく使う形は次のとおりです。

C#
string.Join(string separator, string[] value)

文字列配列を結合する基本的な形です。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

次のように、List<string>などのIEnumerable<string>も結合できます。

C#
string.Join(string separator, IEnumerable<string> values)

使用例です。

C#
List<string> values = new List<string> { "A", "B", "C" };

string result = string.Join(",", values);

ジェネリックなIEnumerable<T>を結合する形もよく使います。

C#
string.Join<T>(string separator, IEnumerable<T> values)

たとえば、List<int>をそのまま結合できます。

C#
List<int> numbers = new List<int> { 1, 2, 3 };

string result = string.Join(",", numbers);

Console.WriteLine(result);

実行結果は次のとおりです。

1,2,3

配列の一部だけを結合するオーバーロードもあります。

C#
string.Join(string separator, string[] value, int startIndex, int count)

使用例です。

C#
string[] values = { "A", "B", "C", "D" };

string result = string.Join(",", values, 1, 2);

Console.WriteLine(result);

実行結果は次のとおりです。

B,C

startIndexは開始位置、countは結合する要素数です。

3. 配列をstring.Joinで結合する使い方

3-1. string配列をカンマ区切りで結合する

もっとも基本的な使い方は、string配列をカンマ区切りで結合する方法です。

C#
string[] languages = { "C#", "Java", "Python" };

string result = string.Join(", ", languages);

Console.WriteLine(result);

実行結果は次のとおりです。

C#, Java, Python

カンマの後にスペースを入れると、人が読みやすい文字列になります。

スペースなしにしたい場合は、区切り文字を,にします。

C#
string result = string.Join(",", languages);

Console.WriteLine(result);

実行結果は次のとおりです。

C#,Java,Python

CSV風の文字列やログ出力では,を使い、画面表示では, を使うなど、用途に応じて使い分けるとよいです。

3-2. スペース区切り・改行区切りで結合する

スペース区切りで結合したい場合は、区切り文字に" "を指定します。

C#
string[] words = { "Hello", "C#", "World" };

string result = string.Join(" ", words);

Console.WriteLine(result);

実行結果は次のとおりです。

Hello C# World

改行区切りで結合したい場合は、Environment.NewLineを使います。

C#
string[] lines =
{
"1行目",
"2行目",
"3行目"
};

string result = string.Join(Environment.NewLine, lines);

Console.WriteLine(result);

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

1行目
2行目
3行目

\nを直接指定することもできます。

C#
string result = string.Join("\n", lines);

ただし、WindowsやLinuxなどの環境差を考慮するなら、通常はEnvironment.NewLineを使うほうが安全です。

3-3. 区切り文字なしで配列を結合する

区切り文字なしで結合したい場合は、第1引数に空文字""を指定します。

C#
string[] values = { "A", "B", "C" };

string result = string.Join("", values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

このケースでは、string.Concatを使っても同じような結果になります。

C#
string result = string.Concat(values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

区切り文字が必要ならstring.Join、単純に全部つなげるだけならstring.Concatも選択肢になります。

3-4. 配列の一部だけを結合する方法

配列の一部だけを結合したい場合は、startIndexcountを指定できるオーバーロードを使います。

C#
string[] values = { "A", "B", "C", "D", "E" };

string result = string.Join(",", values, 1, 3);

Console.WriteLine(result);

実行結果は次のとおりです。

B,C,D

この例では、インデックス1Bから始めて、3個の要素を結合しています。

startIndexは0始まりです。

C#
string[] values = { "A", "B", "C", "D", "E" };
// index: 0 1 2 3 4

LINQを使って一部だけを取り出してから結合する方法もあります。

C#
string[] values = { "A", "B", "C", "D", "E" };

string result = string.Join(",", values.Skip(1).Take(3));

Console.WriteLine(result);

実行結果は次のとおりです。

B,C,D

配列専用の範囲指定ならstring.Join(",", values, 1, 3)、LINQで柔軟に絞り込みたいならSkipTakeを使うとよいです。

3-5. 空の配列を渡した場合の結果

空の配列をstring.Joinに渡すと、結果は空文字になります。

C#
string[] values = Array.Empty<string>();

string result = string.Join(",", values);

Console.WriteLine($"結果: [{result}]");

実行結果は次のとおりです。

結果: []

エラーにはならず、空文字""が返ります。

そのため、要素が0件の可能性がある場合でも、結合対象がnullでなければ安全に使えます。

C#
var values = new List<string>();

string result = string.Join(", ", values);

Console.WriteLine(string.IsNullOrEmpty(result));

実行結果は次のとおりです。

True

ただし、配列そのものがnullの場合は例外になるため注意が必要です。

C#
string[]? values = null;

// ArgumentNullException
string result = string.Join(",", values);

空の配列とnullの配列は挙動が違います。

4. Listをstring.Joinで結合する使い方

4-1. List<string>をカンマ区切りで結合する

string.Joinは、List<string>にもそのまま使えます。

C#
List<string> names = new List<string>
{
"Alice",
"Bob",
"Charlie"
};

string result = string.Join(", ", names);

Console.WriteLine(result);

実行結果は次のとおりです。

Alice, Bob, Charlie

配列と同じ感覚で使えるため、リストの中身を表示したいときに便利です。

C#
var tags = new List<string> { "C#", ".NET", "LINQ" };

Console.WriteLine($"タグ: {string.Join(", ", tags)}");

実行結果は次のとおりです。

タグ: C#, .NET, LINQ

4-2. List<int>など数値リストを結合する

List<int>など、文字列以外のリストも結合できます。

C#
List<int> ids = new List<int> { 101, 102, 103 };

string result = string.Join(", ", ids);

Console.WriteLine(result);

実行結果は次のとおりです。

101, 102, 103

intの各要素は、内部的に文字列に変換されて結合されます。

doubleでも同じように使えます。

C#
List<double> prices = new List<double> { 1200.5, 980.0, 450.75 };

string result = string.Join(", ", prices);

Console.WriteLine(result);

実行結果の例は次のとおりです。

1200.5, 980, 450.75

表示形式を細かく制御したい場合は、LINQのSelectで文字列に変換してから結合します。

C#
List<double> prices = new List<double> { 1200.5, 980.0, 450.75 };

string result = string.Join(", ", prices.Select(x => x.ToString("F2")));

Console.WriteLine(result);

実行結果は次のとおりです。

1200.50, 980.00, 450.75

4-3. List<object>や独自クラスを結合する場合

List<object>や独自クラスのリストもstring.Joinで結合できます。

ただし、その場合は各要素のToString()の結果が使われます。

C#
List<object> values = new List<object>
{
123,
"ABC",
DateTime.Today
};

string result = string.Join(", ", values);

Console.WriteLine(result);

日付の表示は環境やカルチャによって変わる場合があります。

独自クラスの場合も確認してみましょう。

C#
class User
{
public string Name { get; set; } = "";
}

このクラスのリストをそのまま結合すると、期待した表示にならないことがあります。

C#
var users = new List<User>
{
new User { Name = "Alice" },
new User { Name = "Bob" }
};

string result = string.Join(", ", users);

Console.WriteLine(result);

実行結果は、クラス名のような文字列になる場合があります。

User, User

期待どおりに名前を表示したい場合は、ToString()をオーバーライドするか、Selectでプロパティを取り出します。

C#
string result = string.Join(", ", users.Select(user => user.Name));

Console.WriteLine(result);

実行結果は次のとおりです。

Alice, Bob

実務では、独自クラスをそのままstring.Joinに渡すより、表示したいプロパティを明示的に指定するほうが安全です。

4-4. LINQと組み合わせて要素を加工してから結合する

string.JoinはLINQと組み合わせると非常に便利です。

たとえば、文字列を大文字に変換してから結合できます。

C#
var names = new List<string> { "alice", "bob", "charlie" };

string result = string.Join(", ", names.Select(x => x.ToUpper()));

Console.WriteLine(result);

実行結果は次のとおりです。

ALICE, BOB, CHARLIE

数値をフォーマットしてから結合することもできます。

C#
var amounts = new List<decimal> { 1000, 2500, 30000 };

string result = string.Join(", ", amounts.Select(x => $"{x:N0}円"));

Console.WriteLine(result);

実行結果は次のとおりです。

1,000円, 2,500円, 30,000円

ただし、この例では数値の中にもカンマが含まれるため、区切り文字としてのカンマと少し紛らわしくなる場合があります。

その場合は区切り文字を変えると見やすくなります。

C#
string result = string.Join(" / ", amounts.Select(x => $"{x:N0}円"));

Console.WriteLine(result);

実行結果は次のとおりです。

1,000円 / 2,500円 / 30,000円

4-5. Selectを使ってプロパティだけを結合する

実務でよくあるのが、オブジェクトのリストから特定のプロパティだけを結合するケースです。

たとえば、ユーザー一覧から名前だけを取り出して結合します。

C#
class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
}
C#
var users = new List<User>
{
new User { Id = 1, Name = "田中" },
new User { Id = 2, Name = "佐藤" },
new User { Id = 3, Name = "鈴木" }
};

string result = string.Join("、", users.Select(user => user.Name));

Console.WriteLine(result);

実行結果は次のとおりです。

田中、佐藤、鈴木

IDだけを結合することもできます。

C#
string result = string.Join(",", users.Select(user => user.Id));

Console.WriteLine(result);

実行結果は次のとおりです。

1,2,3

Selectを使うことで、必要な値だけを取り出してからstring.Joinに渡せます。

5. 区切り文字の実例パターン

5-1. カンマ区切りの文字列を作る

カンマ区切りは、string.Joinのもっともよくある使い方です。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

人が読むための表示なら、カンマの後にスペースを入れると見やすくなります。

C#
string result = string.Join(", ", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A, B, C

ログに出す場合もよく使います。

C#
var targetIds = new[] { 1001, 1002, 1003 };

Console.WriteLine($"処理対象ID: {string.Join(", ", targetIds)}");

実行結果は次のとおりです。

処理対象ID: 1001, 1002, 1003

5-2. CSV風の文字列を作る

簡単なCSV風の文字列なら、string.Joinで作れます。

C#
string[] row = { "1", "田中", "tanaka@example.com" };

string csvLine = string.Join(",", row);

Console.WriteLine(csvLine);

実行結果は次のとおりです。

1,田中,tanaka@example.com

ただし、値の中にカンマ、ダブルクォート、改行が含まれる場合は、単純なstring.Joinだけでは正しいCSVになりません。

C#
string[] row = { "1", "田中,太郎", "Hello \"C#\"" };

string csvLine = string.Join(",", row);

Console.WriteLine(csvLine);

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

1,田中,太郎,Hello "C#"

この結果では、田中,太郎が2つの列のように見えてしまいます。

簡易的にCSVエスケープするなら、次のような処理が必要です。

C#
static string EscapeCsv(string value)
{
if (value.Contains(",") || value.Contains("\"") || value.Contains("\r") || value.Contains("\n"))
{
return "\"" + value.Replace("\"", "\"\"") + "\"";
}

return value;
}

string[] row = { "1", "田中,太郎", "Hello \"C#\"" };

string csvLine = string.Join(",", row.Select(EscapeCsv));

Console.WriteLine(csvLine);

実行結果は次のとおりです。

1,"田中,太郎","Hello ""C#"""

本格的なCSV出力では、CSVライブラリを使うことも検討しましょう。

5-3. 改行区切りの文字列を作る

複数のメッセージを改行区切りで表示したい場合は、Environment.NewLineを使います。

C#
var messages = new List<string>
{
"入力内容を確認してください。",
"名前は必須です。",
"メールアドレスは必須です。"
};

string result = string.Join(Environment.NewLine, messages);

Console.WriteLine(result);

実行結果は次のとおりです。

入力内容を確認してください。
名前は必須です。
メールアドレスは必須です。

WebアプリケーションでHTMLに表示する場合は、改行コードだけではブラウザ上で改行されない場合があります。

その場合は、<br>で結合することもあります。

C#
string html = string.Join("<br>", messages);

Console.WriteLine(html);

実行結果は次のとおりです。

入力内容を確認してください。<br>名前は必須です。<br>メールアドレスは必須です。

ただし、HTMLに出力する場合は、XSS対策として値のエスケープも考慮する必要があります。

5-4. パスやURL風の文字列を作る

スラッシュ区切りでパスやURL風の文字列を作ることもできます。

C#
string[] parts = { "api", "users", "123" };

string path = string.Join("/", parts);

Console.WriteLine(path);

実行結果は次のとおりです。

api/users/123

URLのパス部分を組み立てるような簡単な用途では便利です。

C#
string baseUrl = "https://example.com";
string[] paths = { "products", "100" };

string url = baseUrl + "/" + string.Join("/", paths);

Console.WriteLine(url);

実行結果は次のとおりです。

https://example.com/products/100

ただし、ファイルパスを作る場合は、string.JoinよりもPath.Combineを使うほうが適切です。

C#
string path = Path.Combine("C:\\work", "logs", "app.txt");

Console.WriteLine(path);

URLの場合も、値にスラッシュや特殊文字が含まれる場合は、適切なエンコードやURI処理が必要です。

5-5. SQLのIN句に使う文字列を作る際の注意点

string.Joinを使うと、SQLのIN句に使うような文字列を簡単に作れます。

C#
int[] ids = { 1, 2, 3 };

string inClause = string.Join(",", ids);

Console.WriteLine(inClause);

実行結果は次のとおりです。

1,2,3

これを使って、次のようにSQLを組み立てたくなるかもしれません。

C#
string sql = $"SELECT * FROM Users WHERE Id IN ({string.Join(",", ids)})";

数値IDだけで、値が完全に信頼できる場合はまだ扱いやすいですが、ユーザー入力を含む文字列を直接SQLに埋め込むのは危険です。

悪い例です。

C#
var names = new[] { "Alice", "Bob" };

string sql = $"SELECT * FROM Users WHERE Name IN ('{string.Join("','", names)}')";

このような書き方は、SQLインジェクションのリスクがあります。

実務では、パラメータ化クエリを使うべきです。

C#
// 考え方の例
// SELECT * FROM Users WHERE Id IN (@id0, @id1, @id2)

string.Joinは、プレースホルダー名を作る用途なら使いやすいです。

C#
int[] ids = { 1, 2, 3 };

var parameterNames = ids.Select((id, index) => $"@id{index}");

string inClause = string.Join(", ", parameterNames);

Console.WriteLine(inClause);

実行結果は次のとおりです。

@id0, @id1, @id2

SQL文そのものに値を直接埋め込むのではなく、パラメータ名の結合に使うのが安全です。

5-6. ログ出力用に配列やリストの中身を見やすく表示する

ログ出力では、配列やリストの中身を見やすく表示したいことがよくあります。

C#
var ids = new List<int> { 101, 205, 309 };

Console.WriteLine($"ids=[{string.Join(", ", ids)}]");

実行結果は次のとおりです。

ids=[101, 205, 309]

文字列のリストも同じです。

C#
var roles = new List<string> { "Admin", "Editor", "Viewer" };

Console.WriteLine($"roles=[{string.Join(", ", roles)}]");

実行結果は次のとおりです。

roles=[Admin, Editor, Viewer]

ログで値の境界を分かりやすくしたい場合は、各要素を引用符で囲むこともあります。

C#
var names = new List<string> { "Alice", "Bob", "Charlie" };

string result = string.Join(", ", names.Select(x => $"\"{x}\""));

Console.WriteLine($"names=[{result}]");

実行結果は次のとおりです。

names=["Alice", "Bob", "Charlie"]

6. null・空文字・空白を含む場合の挙動

6-1. 要素にnullが含まれる場合

string.Joinでは、要素にnullが含まれている場合、その要素は空文字として扱われます。

C#
string?[] values = { "A", null, "C" };

string result = string.Join(",", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A,,C

nullの位置には文字が入りませんが、区切り文字は入ります。

カンマ区切りの場合、A,,Cのように連続したカンマになります。

画面表示やログ出力でこれが分かりにくい場合は、nullを除外するか、別の文字に置き換えるとよいです。

C#
string?[] values = { "A", null, "C" };

string result = string.Join(",", values.Select(x => x ?? "(null)"));

Console.WriteLine(result);

実行結果は次のとおりです。

A,(null),C

6-2. 要素に空文字が含まれる場合

要素に空文字""が含まれる場合も、その位置には文字が入りません。

C#
string[] values = { "A", "", "C" };

string result = string.Join(",", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A,,C

nullと同じように見えますが、意味は異なります。

空文字を除外したい場合は、Wherestring.IsNullOrEmptyを使います。

C#
string[] values = { "A", "", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrEmpty(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,C

6-3. 区切り文字にnullを指定した場合

区切り文字にnullを指定した場合、区切り文字は空文字として扱われます。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(null, values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

つまり、次のコードと同じような結果になります。

C#
string result = string.Join("", values);

ただし、読みやすさの観点では、区切り文字なしで結合したいなら明示的に""を指定するほうが分かりやすいです。

C#
string result = string.Join("", values);

nullを区切り文字として使う意図は伝わりにくいため、通常は避けたほうがよいでしょう。

6-4. 結合対象そのものがnullの場合

結合対象そのものがnullの場合、ArgumentNullExceptionが発生します。

C#
string[]? values = null;

string result = string.Join(",", values);

このコードは例外になります。

空の配列であればエラーにはなりません。

C#
string[] values = Array.Empty<string>();

string result = string.Join(",", values);

Console.WriteLine(result == "");

実行結果は次のとおりです。

True

つまり、次の2つは違います。

C#
string[]? nullArray = null;
string[] emptyArray = Array.Empty<string>();

nullArrayを渡すと例外、emptyArrayを渡すと空文字が返ります。

結合対象がnullの可能性がある場合は、Array.Empty<string>()や空のリストに置き換えてから使うと安全です。

C#
string[]? values = null;

string result = string.Join(",", values ?? Array.Empty<string>());

Console.WriteLine(result);

6-5. nullや空文字を除外して結合する方法

nullや空文字を除外して結合したい場合は、LINQのWhereを使います。

C#
string?[] values = { "A", null, "", "B", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrEmpty(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

空白だけの文字列も除外したい場合は、string.IsNullOrWhiteSpaceを使います。

C#
string?[] values = { "A", null, "", " ", "B", "\t", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrWhiteSpace(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

IsNullOrEmptynullと空文字を除外します。

IsNullOrWhiteSpaceは、null、空文字、スペース、タブなどの空白文字だけの文字列も除外します。

6-6. Where・IsNullOrEmpty・IsNullOrWhiteSpaceを使った実例

実務では、ユーザー入力や任意項目を結合するときに、空の値を除外したいことがあります。

たとえば、住所の各項目を結合する例です。

C#
string? prefecture = "東京都";
string? city = "渋谷区";
string? address1 = "";
string? address2 = "神南1-1-1";

var parts = new[] { prefecture, city, address1, address2 };

string address = string.Join(" ", parts.Where(x => !string.IsNullOrWhiteSpace(x)));

Console.WriteLine(address);

実行結果は次のとおりです。

東京都 渋谷区 神南1-1-1

空文字のaddress1は除外されています。

検索条件の表示にも使えます。

C#
string? keyword = "C#";
string? category = "";
string? status = "公開中";

var conditions = new[]
{
string.IsNullOrWhiteSpace(keyword) ? null : $"キーワード: {keyword}",
string.IsNullOrWhiteSpace(category) ? null : $"カテゴリ: {category}",
string.IsNullOrWhiteSpace(status) ? null : $"ステータス: {status}"
};

string result = string.Join(" / ", conditions.Where(x => !string.IsNullOrWhiteSpace(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

キーワード: C# / ステータス: 公開中

このように、Whereと組み合わせることで、余計な区切り文字のないきれいな文字列を作れます。

7. string.Joinでよくあるエラーと解決方法

7-1. ArgumentNullExceptionが発生する原因

string.JoinArgumentNullExceptionが発生する代表的な原因は、結合対象そのものがnullであることです。

C#
List<string>? names = null;

string result = string.Join(", ", names);

このコードは例外になります。

解決するには、nullの場合に空のコレクションを使います。

C#
List<string>? names = null;

string result = string.Join(", ", names ?? Enumerable.Empty<string>());

Console.WriteLine(result);

結果は空文字です。

配列の場合は、次のように書けます。

C#
string[]? values = null;

string result = string.Join(", ", values ?? Array.Empty<string>());

メソッド化しておくと便利です。

C#
static string JoinSafe(IEnumerable<string>? values)
{
return string.Join(", ", values ?? Enumerable.Empty<string>());
}

使用例です。

C#
List<string>? names = null;

Console.WriteLine(JoinSafe(names));

7-2. 余計なカンマや区切り文字が入る原因

string.Join自体は、最後に余計な区切り文字を付けません。

それでも余計なカンマが入る場合、要素の中にnullや空文字が含まれている可能性があります。

C#
string?[] values = { "A", "", "C" };

string result = string.Join(",", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A,,C

これは、空文字の要素があるためです。

空文字を除外すれば、余計なカンマのように見える部分をなくせます。

C#
string?[] values = { "A", "", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrEmpty(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,C

空白だけの値も除外したい場合は、次のようにします。

C#
string?[] values = { "A", " ", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrWhiteSpace(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,C

7-3. ListをそのままToStringしてしまう失敗例

リストの中身を表示しようとして、ToString()を使ってしまう失敗はよくあります。

C#
var names = new List<string> { "Alice", "Bob", "Charlie" };

Console.WriteLine(names.ToString());

実行結果は、期待した一覧ではなく、型名のような文字列になります。

System.Collections.Generic.List`1[System.String]

リストの中身を表示したい場合は、string.Joinを使います。

C#
var names = new List<string> { "Alice", "Bob", "Charlie" };

Console.WriteLine(string.Join(", ", names));

実行結果は次のとおりです。

Alice, Bob, Charlie

配列でも同じように、ToString()では中身は表示されません。

C#
string[] values = { "A", "B", "C" };

Console.WriteLine(values.ToString());

期待する結果を得るには、次のようにします。

C#
Console.WriteLine(string.Join(", ", values));

7-4. CSV出力でダブルクォートやカンマを正しく扱えない問題

CSVを作るときに、単純にstring.Join(",", values)と書くと、値にカンマやダブルクォートが含まれる場合に問題が起きます。

C#
string[] values = { "1", "田中,太郎", "Hello \"C#\"" };

string csv = string.Join(",", values);

Console.WriteLine(csv);

実行結果は次のとおりです。

1,田中,太郎,Hello "C#"

このままだと、田中,太郎が別々の列として扱われる可能性があります。

CSVとして扱うには、必要な値をダブルクォートで囲み、値の中のダブルクォートを二重にする必要があります。

C#
static string EscapeCsv(string value)
{
if (value.Contains(",") || value.Contains("\"") || value.Contains("\r") || value.Contains("\n"))
{
return "\"" + value.Replace("\"", "\"\"") + "\"";
}

return value;
}

string[] values = { "1", "田中,太郎", "Hello \"C#\"" };

string csv = string.Join(",", values.Select(EscapeCsv));

Console.WriteLine(csv);

実行結果は次のとおりです。

1,"田中,太郎","Hello ""C#"""

CSV出力は一見簡単ですが、仕様を正しく扱うには注意が必要です。

7-5. 日本語や改行を含む文字列を結合する際の注意点

string.Joinは日本語文字列にも問題なく使えます。

C#
string[] names = { "田中", "佐藤", "鈴木" };

string result = string.Join("、", names);

Console.WriteLine(result);

実行結果は次のとおりです。

田中、佐藤、鈴木

ただし、要素に改行が含まれている場合は、出力結果が見づらくなることがあります。

C#
string[] values =
{
"1行目\n2行目",
"別の値"
};

string result = string.Join(", ", values);

Console.WriteLine(result);

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

1行目
2行目, 別の値

ログやCSVに出力する場合は、改行を別の文字に置換することもあります。

C#
string[] values =
{
"1行目\n2行目",
"別の値"
};

string result = string.Join(", ", values.Select(x => x.Replace("\r", "\\r").Replace("\n", "\\n")));

Console.WriteLine(result);

実行結果は次のとおりです。

1行目\n2行目, 別の値

日本語そのものは問題ではありませんが、改行、タブ、カンマ、ダブルクォートなどの特殊な意味を持つ文字をどう扱うかが重要です。

8. string.Joinと他の文字列操作メソッドの使い分け

8-1. string.Joinとstring.Concatの違い

string.Joinstring.Concatは、どちらも複数の文字列を結合できます。

違いは、区切り文字を入れるかどうかです。

C#
string[] values = { "A", "B", "C" };

Console.WriteLine(string.Join(",", values));
Console.WriteLine(string.Concat(values));

実行結果は次のとおりです。

A,B,C
ABC

string.Joinは要素の間に区切り文字を入れます。

string.Concatは区切り文字なしでそのまま連結します。

区切り文字なしでstring.Joinを使うこともできます。

C#
string result = string.Join("", values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

ただし、単純な連結であることを明確にしたいなら、string.Concatのほうが意図が伝わりやすい場合もあります。

8-2. string.JoinとStringBuilderの違い

StringBuilderは、文字列を少しずつ組み立てるためのクラスです。

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

builder.Append("A");
builder.Append(",");
builder.Append("B");
builder.Append(",");
builder.Append("C");

string result = builder.ToString();

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

しかし、配列やリストを区切り文字付きで結合するだけなら、string.Joinのほうが簡潔です。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

ループで複雑な条件分岐をしながら文字列を組み立てるならStringBuilder、既にある要素一覧を区切り文字で結合するならstring.Joinが向いています。

悪い例として、区切り文字の制御を手書きするとコードが複雑になります。

C#
var values = new[] { "A", "B", "C" };
var builder = new System.Text.StringBuilder();

for (int i = 0; i < values.Length; i++)
{
if (i > 0)
{
builder.Append(",");
}

builder.Append(values[i]);
}

Console.WriteLine(builder.ToString());

この処理は、string.Joinなら1行で書けます。

C#
Console.WriteLine(string.Join(",", values));

8-3. string.Joinとstring.Splitの関係

string.Joinstring.Splitは、反対の処理として考えると分かりやすいです。

string.Joinは、配列やリストを1つの文字列に結合します。

C#
string[] values = { "A", "B", "C" };

string joined = string.Join(",", values);

Console.WriteLine(joined);

実行結果は次のとおりです。

A,B,C

string.Splitは、1つの文字列を分割して配列にします。

C#
string text = "A,B,C";

string[] values = text.Split(',');

Console.WriteLine(values[0]);
Console.WriteLine(values[1]);
Console.WriteLine(values[2]);

実行結果は次のとおりです。

A
B
C

つまり、次のような関係です。

C#
string[] values = { "A", "B", "C" };

string joined = string.Join(",", values);
string[] splitted = joined.Split(',');

Console.WriteLine(string.Join(" / ", splitted));

実行結果は次のとおりです。

A / B / C

ただし、要素の中に区切り文字が含まれる場合は、単純なSplitでは元に戻せないことがあります。

C#
string[] values = { "A", "B,C", "D" };

string joined = string.Join(",", values);

Console.WriteLine(joined);

実行結果は次のとおりです。

A,B,C,D

この場合、元のB,Cという1要素だった情報は失われます。

8-4. string.Joinと文字列補間の使い分け

文字列補間は、固定の文章の中に値を埋め込むときに便利です。

C#
string name = "Alice";
int age = 20;

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

Console.WriteLine(message);

実行結果は次のとおりです。

Aliceさんは20歳です。

一方、string.Joinは、複数の要素を同じルールでつなげるときに便利です。

C#
var names = new[] { "Alice", "Bob", "Charlie" };

string message = $"参加者: {string.Join(", ", names)}";

Console.WriteLine(message);

実行結果は次のとおりです。

参加者: Alice, Bob, Charlie

文字列補間とstring.Joinは組み合わせて使うことも多いです。

C#
var ids = new[] { 1, 2, 3 };

string log = $"削除対象ID: [{string.Join(", ", ids)}]";

Console.WriteLine(log);

実行結果は次のとおりです。

削除対象ID: [1, 2, 3]

固定文の中に値を埋めるなら文字列補間、複数要素をまとめるならstring.Joinと考えるとよいです。

8-5. 大量データを扱う場合のパフォーマンス注意点

string.Joinは、配列やリストを区切り文字で結合する用途では非常に便利です。

ただし、大量データを扱う場合は、結果の文字列そのものが非常に大きくなる点に注意が必要です。

C#
var values = Enumerable.Range(1, 1000000);

string result = string.Join(",", values);

このコードは100万個の数値を1つの巨大な文字列にします。

ログ出力や画面表示では、そこまで大きな文字列を作る必要がない場合も多いです。

たとえば、ログには先頭100件だけ出すという方法があります。

C#
var values = Enumerable.Range(1, 1000000);

string result = string.Join(",", values.Take(100));

Console.WriteLine(result);

また、ファイルに大量データを書き出す場合は、すべてを一度にstring.Joinで巨大な文字列にするより、ストリームへ順次書き出すほうが適している場合もあります。

string.Joinは便利ですが、結合結果がどれくらい大きくなるかは意識して使いましょう。

9. 実務で使えるstring.Joinのサンプル集

9-1. ユーザー名一覧をカンマ区切りで表示する

ユーザー名の一覧を画面に表示する例です。

C#
var userNames = new List<string>
{
"田中",
"佐藤",
"鈴木"
};

string displayText = string.Join("、", userNames);

Console.WriteLine(displayText);

実行結果は次のとおりです。

田中、佐藤、鈴木

カンマ区切りにする場合は、次のようにします。

C#
string displayText = string.Join(", ", userNames);

Console.WriteLine(displayText);

実行結果は次のとおりです。

田中, 佐藤, 鈴木

画面表示では、日本語の読点を使うと自然に見えることがあります。

9-2. ID一覧を文字列に変換してAPIやログに出力する

ID一覧をログに出す例です。

C#
var ids = new List<int> { 1001, 1002, 1003 };

string logMessage = $"対象ID: {string.Join(", ", ids)}";

Console.WriteLine(logMessage);

実行結果は次のとおりです。

対象ID: 1001, 1002, 1003

APIに渡すクエリ文字列の一部として使うこともあります。

C#
var ids = new List<int> { 1001, 1002, 1003 };

string query = $"ids={string.Join(",", ids)}";

Console.WriteLine(query);

実行結果は次のとおりです。

ids=1001,1002,1003

ただし、URLに含める値に特殊文字がある場合は、URLエンコードが必要です。

IDのような数値であれば扱いやすいですが、文字列を結合してURLに入れる場合は注意しましょう。

9-3. チェックボックスの選択値を結合する

フォームのチェックボックスで選択された値を結合する例です。

C#
var selectedOptions = new List<string>
{
"メール通知",
"SMS通知",
"アプリ通知"
};

string result = string.Join(", ", selectedOptions);

Console.WriteLine(result);

実行結果は次のとおりです。

メール通知, SMS通知, アプリ通知

未選択の場合は空文字になります。

C#
var selectedOptions = new List<string>();

string result = string.Join(", ", selectedOptions);

Console.WriteLine($"選択値: [{result}]");

実行結果は次のとおりです。

選択値: []

画面表示では、未選択の場合に別メッセージを出すと親切です。

C#
var selectedOptions = new List<string>();

string result = selectedOptions.Any()
? string.Join(", ", selectedOptions)
: "選択されていません";

Console.WriteLine(result);

実行結果は次のとおりです。

選択されていません

9-4. エラーメッセージ一覧を改行区切りで表示する

入力チェックのエラーメッセージを改行区切りで表示する例です。

C#
var errors = new List<string>();

errors.Add("名前を入力してください。");
errors.Add("メールアドレスを入力してください。");
errors.Add("パスワードは8文字以上で入力してください。");

string message = string.Join(Environment.NewLine, errors);

Console.WriteLine(message);

実行結果は次のとおりです。

名前を入力してください。
メールアドレスを入力してください。
パスワードは8文字以上で入力してください。

Web画面にHTMLとして表示するなら、<br>で結合する場合もあります。

C#
string htmlMessage = string.Join("<br>", errors);

Console.WriteLine(htmlMessage);

実行結果は次のとおりです。

名前を入力してください。<br>メールアドレスを入力してください。<br>パスワードは8文字以上で入力してください。

ただし、ユーザー入力を含むメッセージをHTMLに出す場合は、HTMLエスケープを忘れないようにしましょう。

9-5. Dictionaryのキーや値を結合する

Dictionaryのキーだけを結合することもできます。

C#
var scores = new Dictionary<string, int>
{
{ "Alice", 80 },
{ "Bob", 90 },
{ "Charlie", 100 }
};

string keys = string.Join(", ", scores.Keys);

Console.WriteLine(keys);

実行結果は次のとおりです。

Alice, Bob, Charlie

値だけを結合することもできます。

C#
string values = string.Join(", ", scores.Values);

Console.WriteLine(values);

実行結果は次のとおりです。

80, 90, 100

キーと値をセットで表示したい場合は、Selectを使います。

C#
string result = string.Join(", ", scores.Select(x => $"{x.Key}={x.Value}"));

Console.WriteLine(result);

実行結果は次のとおりです。

Alice=80, Bob=90, Charlie=100

設定値やデバッグ情報を見やすく出力するときに便利です。

9-6. 配列・List・LINQを組み合わせた実践例

最後に、配列・リスト・LINQを組み合わせた実践的な例を見てみましょう。

注文情報から、有効な商品名だけを取り出して結合します。

C#
class OrderItem
{
public string Name { get; set; } = "";
public int Quantity { get; set; }
public bool IsCanceled { get; set; }
}
C#
var items = new List<OrderItem>
{
new OrderItem { Name = "ノートPC", Quantity = 1, IsCanceled = false },
new OrderItem { Name = "マウス", Quantity = 2, IsCanceled = false },
new OrderItem { Name = "キーボード", Quantity = 1, IsCanceled = true }
};

string result = string.Join(", ",
items
.Where(item => !item.IsCanceled)
.Select(item => $"{item.Name} x {item.Quantity}")
);

Console.WriteLine(result);

実行結果は次のとおりです。

ノートPC x 1, マウス x 2

キャンセル済みの商品を除外し、表示用の文字列に加工してから結合しています。

このように、string.JoinはLINQと組み合わせることで、実務的な一覧表示にとても使いやすくなります。

10. string.Joinのベストプラクティス

10-1. 読みやすいコードにする書き方

string.Joinは1行で書ける便利なメソッドですが、処理を詰め込みすぎると読みにくくなります。

たとえば、次のコードは少し複雑です。

C#
string result = string.Join(", ", users.Where(x => x.IsActive).OrderBy(x => x.Name).Select(x => x.Name.ToUpper()));

処理が長くなる場合は、途中の結果に名前を付けると読みやすくなります。

C#
var activeUserNames = users
.Where(user => user.IsActive)
.OrderBy(user => user.Name)
.Select(user => user.Name.ToUpper());

string result = string.Join(", ", activeUserNames);

このように分けると、「有効なユーザー名を作る処理」と「結合する処理」が分かりやすくなります。

区切り文字も意味のある変数にすると読みやすくなります。

C#
const string Separator = ", ";

string result = string.Join(Separator, activeUserNames);

10-2. nullや空文字を考慮した安全な書き方

結合対象がnullになる可能性がある場合は、空のコレクションに置き換えてから結合すると安全です。

C#
IEnumerable<string>? values = null;

string result = string.Join(", ", values ?? Enumerable.Empty<string>());

要素のnullや空文字を除外したい場合は、Whereを使います。

C#
string?[] values = { "A", null, "", "B", " " };

string result = string.Join(", ", values.Where(x => !string.IsNullOrWhiteSpace(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A, B

安全に結合する処理をメソッドにしておくのもよい方法です。

C#
static string JoinNonEmpty(string separator, IEnumerable<string?>? values)
{
return string.Join(separator,
values?.Where(x => !string.IsNullOrWhiteSpace(x))
?? Enumerable.Empty<string>());
}

使用例です。

C#
string?[] values = { "A", null, "", "B" };

Console.WriteLine(JoinNonEmpty(", ", values));

実行結果は次のとおりです。

A, B

10-3. CSVやSQL用途で安易に使わないほうがよいケース

string.Joinは、CSVやSQLの文字列作成にも使えますが、安易に使うと問題が起きることがあります。

CSVでは、値にカンマ、ダブルクォート、改行が含まれる場合にエスケープが必要です。

C#
string[] values = { "田中,太郎", "Hello \"C#\"" };

string csv = string.Join(",", values);

このままでは正しいCSVになりません。

SQLでは、ユーザー入力を直接結合するとSQLインジェクションの危険があります。

C#
var names = new[] { "Alice", "Bob" };

string sql = $"SELECT * FROM Users WHERE Name IN ('{string.Join("','", names)}')";

このようなコードは避けるべきです。

CSVでは専用のCSVライブラリやエスケープ処理を使い、SQLではパラメータ化クエリを使いましょう。

string.Joinは、値を安全に変換・検証した後で使うことが大切です。

10-4. 区切り文字を定数化するとよいケース

同じ区切り文字を何度も使う場合は、定数化すると保守しやすくなります。

C#
const string CommaSeparator = ", ";
const string SlashSeparator = "/";

使用例です。

C#
var names = new[] { "Alice", "Bob", "Charlie" };

string result = string.Join(CommaSeparator, names);

Console.WriteLine(result);

実行結果は次のとおりです。

Alice, Bob, Charlie

ログ出力で同じ形式を使う場合にも便利です。

C#
static class Separators
{
public const string Comma = ", ";
public const string Slash = "/";
public const string Pipe = " | ";
}
C#
var values = new[] { "A", "B", "C" };

Console.WriteLine(string.Join(Separators.Pipe, values));

実行結果は次のとおりです。

A | B | C

区切り文字を定数化しておくと、後から", "" / "に変更したい場合などにも対応しやすくなります。

10-5. 可読性とパフォーマンスのバランス

通常の配列やリストを結合する程度であれば、string.Joinは読みやすく実用的です。

C#
string result = string.Join(", ", values);

無理にStringBuilderで手書きする必要はありません。

ただし、非常に大量のデータを結合する場合は、結合後の文字列サイズを意識しましょう。

C#
var values = Enumerable.Range(1, 1000000);

string result = string.Join(",", values);

このようなコードは、大きなメモリを使う可能性があります。

ログ用途なら件数を制限する、ファイル出力なら順次書き込む、画面表示ならページングするなど、用途に合った設計が必要です。

C#
var values = Enumerable.Range(1, 1000000);

string preview = string.Join(", ", values.Take(20));

Console.WriteLine($"先頭20件: {preview}");

読みやすさを優先してよい場面と、メモリ効率を考えるべき場面を分けて考えることが大切です。

11. C#のstring.Joinに関するよくある質問

11-1. string.JoinはListにも使える?

はい、string.JoinListにも使えます。

C#
var list = new List<string> { "A", "B", "C" };

string result = string.Join(",", list);

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

List<string>だけでなく、List<int>などにも使えます。

C#
var numbers = new List<int> { 1, 2, 3 };

string result = string.Join(",", numbers);

Console.WriteLine(result);

実行結果は次のとおりです。

1,2,3

11-2. intやdoubleの配列も結合できる?

はい、intdoubleの配列も結合できます。

C#
int[] numbers = { 1, 2, 3 };

string result = string.Join(", ", numbers);

Console.WriteLine(result);

実行結果は次のとおりです。

1, 2, 3

doubleも結合できます。

C#
double[] values = { 1.5, 2.25, 3.75 };

string result = string.Join(", ", values);

Console.WriteLine(result);

実行結果は次のとおりです。

1.5, 2.25, 3.75

小数点以下の桁数をそろえたい場合は、Selectでフォーマットします。

C#
double[] values = { 1.5, 2.25, 3.75 };

string result = string.Join(", ", values.Select(x => x.ToString("F2")));

Console.WriteLine(result);

実行結果は次のとおりです。

1.50, 2.25, 3.75

11-3. 区切り文字なしで結合するには?

区切り文字なしで結合するには、第1引数に空文字""を指定します。

C#
string[] values = { "A", "B", "C" };

string result = string.Join("", values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

また、区切り文字なしで単純に連結するだけなら、string.Concatも使えます。

C#
string result = string.Concat(values);

Console.WriteLine(result);

実行結果は次のとおりです。

ABC

11-4. 最後に区切り文字は付く?

いいえ、string.Joinでは最後に区切り文字は付きません。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

A,B,C,のように末尾にカンマは付きません。

そのため、ループで手動連結するときのように「最後のカンマを削除する」処理は不要です。

11-5. nullを除外して結合するには?

nullを除外して結合するには、Whereを使います。

C#
string?[] values = { "A", null, "B", null, "C" };

string result = string.Join(",", values.Where(x => x != null));

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

空文字も除外したい場合は、string.IsNullOrEmptyを使います。

C#
string?[] values = { "A", null, "", "B", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrEmpty(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

空白だけの文字列も除外したい場合は、string.IsNullOrWhiteSpaceを使います。

C#
string?[] values = { "A", null, "", " ", "B", "C" };

string result = string.Join(",", values.Where(x => !string.IsNullOrWhiteSpace(x)));

Console.WriteLine(result);

実行結果は次のとおりです。

A,B,C

11-6. string.JoinとStringBuilderはどちらが速い?

単純に配列やリストを区切り文字付きで結合するなら、通常はstring.Joinを使うのが適切です。

C#
var values = new[] { "A", "B", "C" };

string result = string.Join(",", values);

StringBuilderは、複雑な条件分岐をしながら文字列を少しずつ追加するような処理に向いています。

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

foreach (var value in values)
{
if (value != "B")
{
builder.Append(value);
}
}

ただし、区切り文字付きで要素を結合するだけなら、StringBuilderで手書きするよりstring.Joinのほうが読みやすく、ミスも少なくなります。

大量データでは、どちらを使うかだけでなく、そもそも巨大な文字列を作る必要があるかを考えることが重要です。

11-7. Unityでもstring.Joinは使える?

はい、UnityのC#でもstring.Joinは使えます。

たとえば、デバッグログにリストの中身を出す場合に便利です。

C#
using System.Collections.Generic;
using UnityEngine;

public class Sample : MonoBehaviour
{
void Start()
{
List<string> items = new List<string> { "Sword", "Shield", "Potion" };

Debug.Log(string.Join(", ", items));
}
}

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

Sword, Shield, Potion

スコア一覧やアイテム一覧、選択中のタグなどをログに出すときに使えます。

C#
int[] scores = { 100, 200, 300 };

Debug.Log("Scores: " + string.Join(", ", scores));

Unityでも、通常のC#と同じように配列やリストを結合できます。

まとめ

C#で配列やリストを区切り文字付きで結合したい場合は、string.Joinを使うのが基本です。

C#
string result = string.Join(", ", values);

string.Joinを使うと、配列、List<string>List<int>、LINQの結果などを簡単に1つの文字列へ変換できます。

カンマ区切りなら次のように書きます。

C#
string[] values = { "A", "B", "C" };

string result = string.Join(",", values);

実行結果は次のとおりです。

A,B,C

改行区切りなら、Environment.NewLineを使います。

C#
string result = string.Join(Environment.NewLine, values);

区切り文字なしで結合したい場合は、空文字を指定します。

C#
string result = string.Join("", values);

nullや空文字を除外したい場合は、LINQのWhereと組み合わせます。

C#
string result = string.Join(", ", values.Where(x => !string.IsNullOrWhiteSpace(x)));

string.Joinは、画面表示、ログ出力、エラーメッセージ、ID一覧、ユーザー名一覧など、実務で頻繁に使うメソッドです。

一方で、CSVやSQLのようにエスケープやセキュリティが重要な用途では、単純なstring.Joinだけに頼らず、専用の処理やパラメータ化クエリを使う必要があります。

基本形のstring.Join(区切り文字, 結合対象)を覚えておけば、C#で配列やリストを扱う多くの場面で、読みやすく安全な文字列結合を書けるようになります。