C#での開発において、複数の文字列を連結して一つの文字列にする操作は非常に頻繁に発生します。
単純な文字列の結合であれば「+」演算子やstring.Concatでも可能ですが、「要素の間に特定の区切り文字を入れたい」という場合には、string.Joinメソッドが最も強力で便利な選択肢となります。
本記事では、C#のstring.Joinを使用して、配列やリスト、さらにはLINQの結果などを効率的に結合する方法を詳しく解説します。
初心者の方から、パフォーマンスを意識する中級者の方まで役立つ情報を整理しました。
string.Joinの基本概念
string.Joinは、コレクションの各要素を指定した区切り文字(セパレーター)で繋ぎ合わせ、一つの文字列を生成する静的メソッドです。
最大のメリットは、末尾に余計な区切り文字が付かないように自動で制御してくれる点にあります。

なぜstring.Joinを使うのか
自分でループ(foreach)を回して「+」演算子で結合しようとすると、最後の要素の後に区切り文字を入れないための「if文による判定」が必要になり、コードが煩雑になりがちです。
例えば、以下のような処理を自前で書くのは非効率です。
// 避けるべき実装例
var items = new[] { "A", "B", "C" };
var result = "";
for (int i = 0; i < items.Length; i++)
{
result += items[i];
if (i < items.Length - 1)
{
result += ","; // 最後の要素以外にカンマを付ける
}
}
string.Joinを使えば、このような境界条件の処理をすべて内部で完結してくれます。
基本的な構文と使い方
最も一般的な使い方は、第一引数に区切り文字、第二引数に結合したいコレクションを渡す形式です。
using System;
class Program
{
static void Main()
{
// 文字列の配列を用意
string[] fruits = { "Apple", "Banana", "Orange" };
// カンマ区切りで結合
string result = string.Join(", ", fruits);
// 結果を出力
Console.WriteLine(result);
}
}
Apple, Banana, Orange
この例のように、AppleとBananaの間、BananaとOrangeの間にはカンマが入りますが、最後のOrangeの後ろにはカンマが入りません。
これがstring.Joinの利便性です。
様々なデータ型の結合
string.Joinは文字列の配列だけでなく、リストや数値型の配列など、IEnumerable<T>インターフェースを実装しているあらゆるコレクションに対して使用可能です。

リスト(List<T>)を結合する
現代的なC#開発では、固定長の配列よりも動的なList<T>を扱うことが多いでしょう。
string.JoinはIEnumerable<string>を受け取れるため、リストもそのまま渡せます。
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 文字列のリストを作成
List<string> colors = new List<string> { "Red", "Green", "Blue" };
// スラッシュ区切りで結合
string joinedColors = string.Join(" / ", colors);
Console.WriteLine(joinedColors);
}
}
Red / Green / Blue
数値型やオブジェクトを結合する
string.Joinは、要素が文字列でない場合、各要素のToString()メソッドを自動的に呼び出して結合します。
そのため、int型の配列やdouble型のリストなども直接渡すことが可能です。
using System;
class Program
{
static void Main()
{
// 整数型の配列
int[] numbers = { 10, 20, 30, 40, 50 };
// ハイフンで結合
string result = string.Join("-", numbers);
Console.WriteLine(result);
}
}
10-20-30-40-50
以前のバージョンの.NETでは、一度文字列の配列に変換する必要がありましたが、現在のC#(.NET Framework 4.0以降)では、ジェネリック版のオーバーロードが提供されているため、そのまま渡してもパフォーマンス上のオーバーヘッドが最小限に抑えられています。
LINQと組み合わせた高度な結合
string.Joinの真価を発揮するのが、LINQ(Language Integrated Query)と組み合わせたときです。
データのフィルタリングや加工を行った後に、一気に文字列としてまとめ上げることができます。

条件に一致する要素だけを結合する
例えば、リストの中から特定の条件を満たすものだけを選び出し、それを結合したい場合はWhere句を使用します。
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
var names = new List<string> { "Alice", "Bob", "Charlie", "David", "Eve" };
// 名前が4文字以上の人だけを抽出してカンマで繋ぐ
string result = string.Join(", ", names.Where(n => n.Length >= 4));
Console.WriteLine("Filtered names: " + result);
}
}
Filtered names: Alice, Charlie, David
要素を加工してから結合する
各要素に対してプレフィックスを付けたり、特定のプロパティを取り出したりする場合は、Select句を組み合わせます。
using System;
using System.Linq;
class Program
{
static void Main()
{
var scores = new[] { 80, 95, 70 };
// 各数値の前に「Score:」を付けて結合
string result = string.Join(" | ", scores.Select(s => $"Score:{s}"));
Console.WriteLine(result);
}
}
Score:80 | Score:95 | Score:70
このように、Selectで加工した結果をそのままstring.Joinに渡すパターンは、実務で非常によく使われるイディオム(定番の書き方)です。
範囲を指定して結合する
配列の一部だけを結合したい場合には、引数にstartIndexとcountを指定できるオーバーロードが便利です。
using System;
class Program
{
static void Main()
{
string[] alphabet = { "A", "B", "C", "D", "E", "F" };
// インデックス2(C)から3つ分を結合
string partial = string.Join("-", alphabet, 2, 3);
Console.WriteLine(partial);
}
}
C-D-E
この方法を使えば、配列をわざわざコピーしたり、新しいリストを作成したりすることなく、メモリを節約しながら部分的な結合が行えます。
パフォーマンスと内部動作
文字列の結合において、パフォーマンスは非常に重要な関心事です。
なぜ「+」演算子ではなくstring.Joinを使うべきなのか、その理由を解説します。
文字列演算子(+)との比較
C#のstring型は「不変(Immutable)」なオブジェクトです。
つまり、一度作成された文字列の内容を後から変更することはできません。
「+」演算子で文字列を連結するたびに、新しいメモリ領域が確保され、古い内容がコピーされるという動作が発生します。

ループ内で「+」を使って結合を繰り返すと、ループ回数に比例して一時的なゴミ文字列が大量に生成され、ガベージコレクション(GC)の負荷が高まってしまいます。
一方、string.Joinは内部的にStringBuilderのような効率的なバッファ管理を行っており、最終的な文字列の長さを予測して最適なメモリ割り当てを行います。
大量の要素を結合する場合は、必ずstring.Joinを使用するようにしましょう。
区切り文字にnullや空文字を指定した場合
意外と知られていないのが、区切り文字(separator)にnullや空文字("")を指定した時の挙動です。
| 指定した値 | 挙動 |
|---|---|
"" (空文字) | 要素間に何も挟まずに連結されます。 |
null | 空文字を指定した場合と同じ挙動になります(例外は発生しません)。 |
string[] parts = { "Hyper", "Text", "Markup" };
// 空文字で結合
string result = string.Join("", parts);
Console.WriteLine(result); // HyperTextMarkup
もし、区切り文字が不要で、かつ非常に大量の要素を結合するのであれば、string.Concatというメソッドも検討に値します。
string.Concatは「区切り文字なし」に特化しているため、わずかに高速な場合があります。
string.Join使用時の注意点
要素がnullの場合の扱い
結合対象のコレクションの中にnullが含まれている場合、string.Joinはそれを空文字列として扱います。
例外がスローされることはありませんが、意図しない区切り文字の連続が発生する可能性があります。
string[] data = { "One", null, "Three" };
string result = string.Join(",", data);
// 結果: One,,Three (カンマが2つ続く)
もしnullを取り除きたい場合は、前述したLINQのWhereを使って事前にフィルタリングを行いましょう。
string result = string.Join(",", data.Where(s => s != null));
// 結果: One,Three
多次元配列には対応していない
string.Joinが直接受け取れるのは1次元のコレクション(IEnumerable)です。
2次元配列などをそのまま渡しても、期待通りにすべての要素を結合することはできません。
その場合は、Cast<T>メソッドなどを使って1次元に平坦化(Flatten)する必要があります。
まとめ
C#のstring.Joinは、コレクションを一つの文字列にまとめるための最も効率的で洗練された方法です。
最後に、重要なポイントを振り返ります。
| 特徴 | 詳細 |
|---|---|
| 末尾の処理 | 最後の要素の後ろには区切り文字を入れないよう自動調整される。 |
| 対応型 | 文字列だけでなく、int型などのオブジェクトやList型にも対応。 |
| LINQ連携 | WhereやSelectと組み合わせることで柔軟なデータ加工が可能。 |
| 性能 | 「+」演算子によるループ結合よりもメモリ効率が非常に高い。 |
「複数の要素を何かで繋ぎたい」と思ったら、まずはstring.Joinを検討する。
これだけで、コードの可読性とアプリケーションのパフォーマンスの両方を向上させることができます。
日々のコーディングにおいて、積極的に活用していきましょう。
