はじめに 「文字列結合」は“バラした情報を一つの形にまとめる”技
さっきまで「文字列分割」でバラす話をしてきましたが、
業務ではその逆——「バラバラの情報を 1 本の文字列にまとめる」場面も同じくらい多いです。
CSV の 1 行を組み立てる。
ログの 1 行を組み立てる。
画面表示用のメッセージを組み立てる。
API に渡すパラメータ文字列を組み立てる。
これらは全部「文字列結合」です。
C# には + 演算子、string.Concat、string.Join、StringBuilder など、
文字列を結合するための手段がいくつもあります。
ただ、何でも + でつなぎ始めると、読みづらくなったり、パフォーマンスが悪くなったりします。
ここでは、初心者向けに、
文字列結合の基本パターンstring.Join を使った「区切り付き結合」
大量結合での StringBuilder の使いどころ
null や空文字をどう扱うかを決めたユーティリティ
を、例題付きで丁寧に解説していきます。
一番シンプルな文字列結合 + と 補間文字列
+ 演算子でつなぐ
まずは一番素朴なやり方から。
string firstName = "Taro";
string lastName = "Yamada";
string fullName = lastName + " " + firstName;
Console.WriteLine(fullName); // Yamada Taro
C#+ で文字列同士をつなぐだけです。
少ない要素をサクッとつなぐだけなら、これで十分です。
ただし、要素が増えてくると、こうなります。
string message =
"ID=" + id + ", Name=" + name + ", Status=" + status + ", Date=" + date;
C#読みづらいし、どこに区切りがあるのかも分かりにくくなってきます。
補間文字列($””)で読みやすくする
C# には「文字列補間」という便利な書き方があります。
string message = $"ID={id}, Name={name}, Status={status}, Date={date}";
C#$"..." の中に {変数} と書くと、その値が埋め込まれます。+ でつなぐよりも、目で見て意味が追いやすくなります。
少数の値を埋め込むときは、+ よりも「補間文字列」を使うほうが、実務では圧倒的に読みやすいです。
重要ポイント① 区切り付きでたくさん結合するときは string.Join
「カンマ区切り」「改行区切り」は Join 一択
配列やリストを「区切り文字付きで 1 本の文字列にしたい」場面は、業務でめちゃくちゃ多いです。
例えば、ID のリストを "1,2,3" にしたいとき。
int[] ids = { 1, 2, 3 };
string s = string.Join(",", ids);
Console.WriteLine(s); // 1,2,3
C#string.Join は、
第 1 引数:区切り文字(string)
第 2 引数:配列や IEnumerable
という形で、「区切り付き結合」をしてくれます。
文字列の配列でも同じです。
string[] names = { "Alice", "Bob", "Charlie" };
string s = string.Join(" / ", names);
Console.WriteLine(s); // Alice / Bob / Charlie
C#ここでのポイントは、「自分で最後の区切りを気にしなくていい」ことです。
+ で書こうとすると、よくこういうコードになります。
string s = "";
for (int i = 0; i < names.Length; i++)
{
if (i > 0)
{
s += ", ";
}
s += names[i];
}
C#string.Join を使えば、この「最初だけ区切りを付けない」ロジックを全部隠せます。
null や空文字をどうするか
string.Join は、要素が null の場合、空文字として扱います。
string?[] values = { "A", null, "C" };
string s = string.Join(",", values);
Console.WriteLine(s); // A,,C
C#null のところが「何もない」扱いになり、区切りだけが残ります。
これで困る場合は、事前にフィルタしておくユーティリティを用意するとよいです。
using System;
using System.Collections.Generic;
public static class JoinUtil
{
public static string JoinNonEmpty(string separator, IEnumerable<string?> values)
{
var list = new List<string>();
foreach (var v in values)
{
if (string.IsNullOrWhiteSpace(v))
{
continue;
}
list.Add(v.Trim());
}
return string.Join(separator, list);
}
}
C#使い方の例です。
string?[] values = { " A ", null, " ", "C" };
string s = JoinUtil.JoinNonEmpty(",", values);
Console.WriteLine(s); // A,C
C#「null や空白だけの要素は捨てて、トリムしたうえで結合する」というルールを
ユーティリティに閉じ込めておくと、後から読み返したときも意図が分かりやすくなります。
重要ポイント② 大量結合では StringBuilder を意識する
+ をループで回すとパフォーマンスが悪くなる理由
こんなコードを考えてみます。
string s = "";
for (int i = 0; i < 10000; i++)
{
s += i.ToString() + ",";
}
C#一見シンプルですが、これはパフォーマンス的にはあまり良くありません。
文字列は「イミュータブル(不変)」なので、+= するたびに「新しい文字列」が作られます。
つまり、ループのたびに、
元の文字列をコピー
新しい部分をくっつける
古い文字列は捨てられる
という処理が走ります。
回数が少なければ気になりませんが、
何万回、何十万回と繰り返すと、無駄なメモリコピーが積み重なって重くなります。
StringBuilder を使った結合
大量に結合する場合は、StringBuilder を使うのが定番です。
using System.Text;
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
if (i > 0)
{
sb.Append(',');
}
sb.Append(i);
}
string s = sb.ToString();
C#StringBuilder は「中身を書き換え可能なバッファ」を持っていて、Append するたびに新しい文字列を作るのではなく、
内部のバッファにどんどん書き足していきます。
そのため、
ループで何度も結合する
大量の行を 1 本の文字列にまとめる
テンプレートから大きなテキストを生成する
といった場面では、+ よりも StringBuilder のほうが圧倒的に効率的です。
重要ポイント③ 「フォーマット+結合」をユーティリティに閉じ込める
ログメッセージの組み立てを例にする
業務でよくあるのが、「ログの 1 行を組み立てる」処理です。
例えば、こういうログを出したいとします。
[2025-02-01 10:00:00] INFO UserId=123 Action=Login Result=Success
これを毎回手書きすると、だいたいこうなります。
string log =
"[" + timestamp + "] " + level +
" UserId=" + userId +
" Action=" + action +
" Result=" + result;
C#補間文字列を使っても、似たような感じです。
string log =
$"[{timestamp}] {level} UserId={userId} Action={action} Result={result}";
C#ここで一歩進めて、「ログ用のフォーマット+結合」をユーティリティにしてしまうと、
呼び出し側がかなりスッキリします。
public static class LogFormatter
{
public static string Format(
DateTime timestamp,
string level,
int userId,
string action,
string result)
{
return $"[{timestamp:yyyy-MM-dd HH:mm:ss}] {level} " +
$"UserId={userId} Action={action} Result={result}";
}
}
C#使い方はこうです。
string log = LogFormatter.Format(
DateTime.Now,
"INFO",
123,
"Login",
"Success");
Console.WriteLine(log);
C#「どんな形で結合するか」をユーティリティ側に閉じ込めておくことで、
ログのフォーマットを変えたいときに、1 箇所直せばいい
呼び出し側のコードが“何をしたいか”だけに集中できる
というメリットが生まれます。
重要ポイント④ null や空文字をどう結合するかを決めておく
「null は空文字扱い」か「null は無視」か
文字列結合で地味に悩ましいのが、「null が混ざったときどうするか」です。
例えば、こういうケース。
string? firstName = "Taro";
string? middleName = null;
string? lastName = "Yamada";
C#これを「スペース区切りで結合したい」とします。
単純に補間文字列で書くと、
string fullName = $"{lastName} {middleName} {firstName}";
C#middleName が null の場合、"Yamada Taro" のようにスペースが 2 つ続いてしまいます。
ここは、「どう扱うか」をユーティリティとして決めてしまうと楽です。
null や空文字を無視して結合するユーティリティ
using System;
using System.Collections.Generic;
public static class JoinUtil
{
public static string JoinWithSpaceIgnoreEmpty(params string?[] values)
{
var list = new List<string>();
foreach (var v in values)
{
if (string.IsNullOrWhiteSpace(v))
{
continue;
}
list.Add(v.Trim());
}
return string.Join(" ", list);
}
}
C#使い方の例です。
string? firstName = "Taro";
string? middleName = null;
string? lastName = "Yamada";
string fullName = JoinUtil.JoinWithSpaceIgnoreEmpty(lastName, middleName, firstName);
Console.WriteLine(fullName); // Yamada Taro
C#このユーティリティは、
null
空文字
空白だけ
を全部「無視」してくれます。
そのうえで、残ったものをスペース区切りで結合します。
こういう「null や空文字をどう扱うか」のルールを、
ユーティリティとして明文化しておくと、
チームでコードを読んだときにも意図が伝わりやすくなります。
まとめ 「文字列結合ユーティリティ」は“情報をきれいな形に整える仕上げ道具”
文字列結合は、ただ + でつなぐだけではなく、
どの手段を使うか(+/補間文字列/Join/StringBuilder)
区切り文字をどう扱うか
null や空文字をどう扱うか
フォーマットと結合をどこまでユーティリティに閉じ込めるか
まで含めて設計すると、一気に「業務で使える」レベルになります。
押さえておきたいポイントをコンパクトにまとめると、
+ と補間文字列は「少数の値」をつなぐときに使う。
配列やリストを区切り付きで結合するときは string.Join 一択。
大量結合やループ内結合では StringBuilder を意識する。
null や空文字をどう扱うか(無視する/空文字扱いする)を決めたユーティリティを用意しておくと、呼び出し側がスッキリする。
ここまで理解できれば、「なんとなく + でつないでいる」段階から抜け出して、
“情報をきれいな文字列に仕上げる”という視点で、
文字列結合を設計できるようになっていきます。

