C# Tips | 文字列処理:文字列結合

C# C#
スポンサーリンク

はじめに 「文字列結合」は“バラした情報を一つの形にまとめる”技

さっきまで「文字列分割」でバラす話をしてきましたが、
業務ではその逆——「バラバラの情報を 1 本の文字列にまとめる」場面も同じくらい多いです。

CSV の 1 行を組み立てる。
ログの 1 行を組み立てる。
画面表示用のメッセージを組み立てる。
API に渡すパラメータ文字列を組み立てる。

これらは全部「文字列結合」です。

C# には + 演算子、string.Concatstring.JoinStringBuilder など、
文字列を結合するための手段がいくつもあります。
ただ、何でも + でつなぎ始めると、読みづらくなったり、パフォーマンスが悪くなったりします。

ここでは、初心者向けに、

文字列結合の基本パターン
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 や空文字をどう扱うか(無視する/空文字扱いする)を決めたユーティリティを用意しておくと、呼び出し側がスッキリする。

ここまで理解できれば、「なんとなく + でつないでいる」段階から抜け出して、
“情報をきれいな文字列に仕上げる”という視点で、
文字列結合を設計できるようになっていきます。

タイトルとURLをコピーしました