はじめに 「文字列分割」は“バラしてから意味をつける”ための基本技
業務システムでは、「1本の文字列の中に、複数の値が詰め込まれている」ことがよくあります。
CSV の 1 行、区切り文字付きの設定値、ユーザーが入力した「A,B,C」形式のリストなどです。
こういうときに必ず使うのが「文字列分割」です。
C# には string.Split という強力なメソッドがありますが、そのまま使うと「空要素が混ざる」「空白が残る」「null で落ちる」など、地味なトラブルが起きがちです。
ここでは、初心者向けに、
string.Split の基本
よくある落とし穴(空要素・空白・null)
実務で使える「安全な分割ユーティリティ」
カンマ区切り・改行区切りなどの具体例
を、かみ砕いて解説していきます。
string.Split の基本を押さえる
一番シンプルな使い方
まずは、素の Split から見てみます。
string s = "A,B,C";
string[] parts = s.Split(',');
foreach (var p in parts)
{
Console.WriteLine($"[{p}]");
}
C#出力はこうなります。
[A][B][C]
カンマ , を区切り文字として、"A", "B", "C" に分割されています。
ここまでは直感通りで分かりやすいですね。
区切り文字は複数指定できる
Split は、区切り文字を複数指定することもできます。
string s = "A,B;C D";
char[] separators = { ',', ';', ' ' };
string[] parts = s.Split(separators);
foreach (var p in parts)
{
Console.WriteLine($"[{p}]");
}
C#この場合、カンマ・セミコロン・スペースのどれかが来たら区切る、という動きになります。
ただし、このままだと「空文字要素」が混ざりやすい、という問題が出てきます。
重要ポイント① 空要素をどう扱うか
そのまま Split すると“空のかけら”が混ざる
例えば、こんな文字列を考えます。
string s = "A,,B, ,C,";
string[] parts = s.Split(',');
C#このときの parts の中身はこうなります。
"A"""(A と B の間の連続カンマ)"B"" "(スペースだけ)"C"""(末尾のカンマ)
多くの場合、「空文字」や「空白だけ」の要素は要りません。
でも、素の Split は容赦なくそれらも配列に入れてきます。
これを放置すると、
要素数を数えたときにズレる
ループ処理で余計なケース分けが増える
「空文字なのに値があると勘違いする」バグが出る
といった地味なトラブルにつながります。
StringSplitOptions で空要素を除外する
ここで使いたいのが StringSplitOptions です。
string s = "A,,B, ,C,";
string[] parts = s.Split(
new[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
foreach (var p in parts)
{
Console.WriteLine($"[{p}]");
}
C#RemoveEmptyEntries を指定すると、「区切り文字の間に何もないところ」は結果から除外されます。
この例だと、"" の要素は消えますが、" "(スペースだけ)は残ります。
つまり、
「本当に空の要素」は消える
「空白だけの要素」は残る
という挙動です。
実務では、「空白だけも要らない」ことが多いので、ここにもう一手間加えます。
重要ポイント② トリムと組み合わせて“きれいな配列”にする
分割後に Trim する
「空白だけの要素も消したい」「前後の空白を落としたい」という場合、
分割したあとに Trim() をかけて整えるのが定番です。
using System;
using System.Collections.Generic;
public static class SplitUtil
{
public static string[] SplitAndTrim(
string? value,
char separator,
bool removeEmpty = true)
{
if (string.IsNullOrWhiteSpace(value))
{
return Array.Empty<string>();
}
string[] raw = value.Split(
new[] { separator },
removeEmpty ? StringSplitOptions.RemoveEmptyEntries
: StringSplitOptions.None);
var list = new List<string>(raw.Length);
foreach (string item in raw)
{
string trimmed = item.Trim();
if (removeEmpty && trimmed.Length == 0)
{
continue;
}
list.Add(trimmed);
}
return list.ToArray();
}
}
C#ここでやっていることを整理します。
null や空白だけの文字列が来たら、空配列を返す。Split で一旦分割する(空要素を除外するかどうかは引数で制御)。
各要素に Trim() をかけて前後の空白を削る。removeEmpty が true の場合、トリム後に空文字になった要素は捨てる。
これで、「空要素」「空白だけの要素」「前後に空白が付いた要素」をきれいに処理できます。
具体例で動きを確認する
Console.WriteLine("---- 1 ----");
foreach (var x in SplitUtil.SplitAndTrim("A,B,C", ',', true))
{
Console.WriteLine($"[{x}]"); // [A][B][C]
}
Console.WriteLine("---- 2 ----");
foreach (var x in SplitUtil.SplitAndTrim("A,,B, ,C,", ',', true))
{
Console.WriteLine($"[{x}]"); // [A][B][C]
}
Console.WriteLine("---- 3 ----");
foreach (var x in SplitUtil.SplitAndTrim(" A , B , C ", ',', true))
{
Console.WriteLine($"[{x}]"); // [A][B][C]
}
C#「入力が多少汚れていても、結果はきれいな配列になる」という状態を作っておくと、
後続の処理がかなり楽になります。
重要ポイント③ null をどう扱うか
そのまま Split を呼ぶと NullReferenceException
よくあるパターンがこれです。
string? s = GetFromConfig(); // null かもしれない
string[] parts = s.Split(','); // s が null だと落ちる
C#Split はインスタンスメソッドなので、レシーバーが null だと NullReferenceException になります。
実務では「null かもしれない文字列」は山ほど出てくるので、
分割処理も「null 安全」にしておくと安心です。
null のときは「空配列」を返す設計
先ほどの SplitAndTrim では、最初にこうしていました。
if (string.IsNullOrWhiteSpace(value))
{
return Array.Empty<string>();
}
C#string.IsNullOrWhiteSpace は、
null
空文字 ""
空白だけ " "
をまとめて「中身なし」とみなしてくれます。
ここで「空配列を返す」というルールにしておくと、呼び出し側はこう書けます。
string? raw = GetFromConfig();
foreach (var item in SplitUtil.SplitAndTrim(raw, ',', true))
{
// null かどうかを気にせず回せる
}
C#「null かもしれない」「空文字かもしれない」を毎回 if でチェックしなくてよくなるので、
コードがかなりスッキリします。
カンマ区切りの“IDリスト”を扱うユーティリティ例
よくある「ID のカンマ区切り」を安全にパースする
業務で本当によく出てくるのが、「ID をカンマ区切りで持っている」パターンです。
"1,2,3"" 10 , 20 , 30 ""1,,2, ,3"
これを int[] に変換したいとき、Split と int.Parse をそのまま組み合わせると、すぐに例外祭りになります。
ここは、分割とトリムと数値変換をまとめたユーティリティを用意してしまうのがおすすめです。
using System;
using System.Collections.Generic;
public static class IdListParser
{
public static int[] ParseIntList(string? value, char separator = ',')
{
string[] parts = SplitUtil.SplitAndTrim(value, separator, removeEmpty: true);
var list = new List<int>(parts.Length);
foreach (string p in parts)
{
if (int.TryParse(p, out int id))
{
list.Add(id);
}
else
{
// 数値に変換できないものは無視するか、例外にするかは要件次第
// ここでは「無視する」方針にしている
}
}
return list.ToArray();
}
}
C#使い方の例です。
foreach (var id in IdListParser.ParseIntList("1,2,3"))
{
Console.WriteLine(id); // 1 2 3
}
foreach (var id in IdListParser.ParseIntList(" 10 , , 20 , x , 30 "))
{
Console.WriteLine(id); // 10 20 30
}
C#ここまでやっておくと、
空要素
空白
変な文字
を全部吸収したうえで、「まともな ID だけの配列」が手に入ります。
改行区切り・タブ区切りなどへの応用
区切り文字を変えるだけで応用できる
SplitAndTrim は、区切り文字を引数で受け取るようにしてあるので、
カンマ以外にも簡単に応用できます。
改行区切りのリスト。
string s = "A\nB\r\nC";
string[] lines = SplitUtil.SplitAndTrim(s, '\n', true);
// あるいは Environment.NewLine を意識した実装にしてもよい
C#タブ区切りの値。
string s = "A\tB\tC";
string[] cols = SplitUtil.SplitAndTrim(s, '\t', true);
C#もし「複数種類の区切り文字」を扱いたい場合は、char separator を char[] separators に変えて、Split の呼び出しを少し変えれば対応できます。
まとめ 「文字列分割ユーティリティ」は“汚い入力をきれいな配列に変えるフィルタ”
文字列分割は、単に Split を呼ぶだけではなく、
空要素
空白だけの要素
前後の空白
null
といった“現実の汚れ”をどう扱うかまで含めて設計すると、一気に実務レベルになります。
押さえておきたいポイントはこうです。
string.Split はそのままだと空要素を含むので、StringSplitOptions.RemoveEmptyEntries を意識する。
分割後に Trim() をかけて、前後の空白や「空白だけの要素」を整理すると、後続処理が楽になる。
null や空白だけの入力は、「空配列を返す」ユーティリティにしておくと、呼び出し側の if が減る。
カンマ区切りの ID リストなど、よく出るパターンは「分割+トリム+型変換」をまとめた専用ユーティリティにしてしまうと強い。
ここまでできれば、「とりあえず Split してるだけ」の段階から抜け出して、
“汚い文字列をきれいな配列に変えるフィルタ”として、文字列分割を設計できるようになります。
