C# Tips | 文字列処理:小文字変換

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

はじめに 「小文字変換」は“ゆるく受け入れて、きっちり比べる”ための道具

大文字変換と同じくらい、業務コードでよく使うのが「小文字変換(Lower)」です。
特に、こんな場面で出てきます。

ユーザー入力を小文字にそろえてから比較したい。
URL やメールアドレスを小文字で扱うルールにしたい。
ログやファイル名を小文字で統一しておきたい。

C# には ToLower というメソッドがありますが、
「とりあえず全部 ToLower しておくか」と雑に使うと、やっぱり落とし穴があります。

ここでは、プログラミング初心者向けに、小文字変換の基本と、
実務で“ちゃんと使える形”にするためのユーティリティ化を、例題付きで丁寧に解説します。


C# の ToLower の基本

一番シンプルな使い方

まずは、素の ToLower から。

string s = "Abc123";

string lower = s.ToLower();

Console.WriteLine(lower); // abc123
C#

英字は小文字に、数字や記号、日本語はそのままです。

string s = "ID: Ab-123 テスト";

string lower = s.ToLower();

Console.WriteLine(lower); // id: ab-123 テスト
C#

ここまでは直感通りで、特に難しくありません。

ただし、ToLower()ToUpper() と同じく、「カルチャ(文化圏)」の影響を受けます。


重要ポイント① ToLower も“カルチャ依存”である

カルチャによって結果が変わる可能性がある

ToLower() を引数なしで呼ぶと、「現在のスレッドのカルチャ」に基づいて小文字変換が行われます。
多くの日本語環境ではあまり問題になりませんが、
一部の言語(トルコ語など)では、「大文字・小文字の対応」が特殊です。

そのため、「どの国のルールで小文字にするか」を意識せずに使うと、
環境によって結果が変わる可能性があります。

業務システムで「比較や検索のために小文字にそろえる」場合、
ここはちゃんと押さえておいたほうがいいポイントです。


重要ポイント② 比較や検索には ToLowerInvariant を使う

“カルチャに左右されたくない”ときの書き方

英字の大文字・小文字を区別せずに比較したいとき、
よくやりがちなのが次のような書き方です。

bool IsSameCode(string? left, string? right)
{
    if (left is null || right is null)
    {
        return false;
    }

    return left.ToLower() == right.ToLower();
}
C#

一見それっぽいですが、問題が二つあります。

カルチャ依存の ToLower() を使っていること。
毎回 null チェックを書かないといけないこと。

ここで使いたいのが、

ToLowerInvariant()

です。

これは、「カルチャに依存しない(不変な)ルールで小文字変換する」メソッドです。
比較や検索のために大文字小文字をそろえるときは、基本的にこちらを使うのが安全です。


null 安全な小文字変換ユーティリティ

そのまま ToLower を呼ぶと null で落ちる

よくあるパターンがこれです。

string? code = GetCodeOrNull();

string lower = code.ToLowerInvariant(); // code が null だと NullReferenceException
C#

code が null の可能性があるのに、そのまま ToLowerInvariant() を呼ぶと落ちます。
実務では「null かもしれない文字列」はたくさん出てくるので、
小文字変換も「null 安全」にしておくと安心です。

ToLowerSafe の実装

public static class StringCaseUtil
{
    public static string ToLowerSafe(string? value)
    {
        return value?.ToLowerInvariant() ?? string.Empty;
    }
}
C#

ここで使っている構文を分解すると、こうなります。

value?.ToLowerInvariant() は、「value が null でなければ ToLowerInvariant を呼び、null なら null のまま」という意味です。
その結果に対して ?? string.Empty を適用しているので、
最終的に「null なら空文字、それ以外なら小文字化された文字列」が返ってきます。

使い方の例です。

string? raw = GetUserInputOrNull();

string normalized = StringCaseUtil.ToLowerSafe(raw);

Console.WriteLine(normalized); // 必ず null ではない
C#

これで、呼び出し側は「null かもしれない」をいちいち気にせずに済みます。


小文字変換+比較をユーティリティに閉じ込める

EqualsIgnoreCase を小文字ベースで書く

大文字変換のときと同じように、「大文字小文字を無視した比較」を
小文字変換ベースで書くこともできます。

public static class StringCaseUtil
{
    public static string ToLowerSafe(string? value)
    {
        return value?.ToLowerInvariant() ?? string.Empty;
    }

    public static bool EqualsIgnoreCase(string? left, string? right)
    {
        string l = ToLowerSafe(left);
        string r = ToLowerSafe(right);

        return l == r;
    }
}
C#

使い方の例です。

string? input = "AbC123";
string? master = "abc123";

if (StringCaseUtil.EqualsIgnoreCase(input, master))
{
    Console.WriteLine("一致");
}
else
{
    Console.WriteLine("不一致");
}
C#

input"ABC123" でも "abc123" でも "aBc123" でも、
同じとみなされます。

大文字ベースにするか、小文字ベースにするかは好みですが、
どちらにせよ「Invariant(カルチャ非依存)」+「null 安全」をセットで考えるのがポイントです。


小文字変換が特に効く場面

メールアドレスや URL の扱い

メールアドレスや URL は、仕様上「大文字小文字を区別しない」とされる部分が多いです。
そのため、実務では「全部小文字にそろえて扱う」ことがよくあります。

例えば、ユーザー登録時にこうします。

string? rawEmail = ReadFromTextBox();

string email = StringCaseUtil.ToLowerSafe(rawEmail).Trim();

user.Email = email;
C#

こうしておくと、

User@Example.com
user@example.com

のような揺れを吸収して、同じメールアドレスとして扱えます。

ファイル名やキーの正規化

ファイル名やキー文字列を「小文字にそろえて保存する」パターンもよくあります。

例えば、キャッシュのキーを小文字にそろえておけば、

"User:123"
"user:123"

のような違いを気にせずに済みます。

string MakeCacheKey(string rawKey)
{
    return StringCaseUtil.ToLowerSafe(rawKey).Trim();
}
C#

「とりあえず全部小文字にしてから使う」というルールを決めておくと、
後から「大文字小文字の違いで別物扱いされていた」という事故を防ぎやすくなります。


小文字変換と他の正規化処理の組み合わせ

実務では“単体”で使わないことが多い

現実の入力値は、だいたいこうです。

前後に空白が付いている。
全角英数字が混ざっている。
大文字小文字がバラバラ。

例えば、ユーザーが入力したコードがこうだとします。

" AbC123 "

これをマスタの "abc123" と比較したいとき、
やりたいことはこうです。

前後の空白をトリムする。
全角英数字を半角にそろえる。
小文字にそろえる。

これを毎回バラバラに書くとつらいので、
「比較用に正規化するユーティリティ」としてまとめてしまうのが現実的です。

コード例:小文字ベースのコード正規化

public static class CodeNormalizeUtil
{
    public static string NormalizeCodeToLower(string? value)
    {
        string s = value ?? string.Empty;

        s = StringTrimUtil.TrimWithZenkaku(s);      // 空白トリム(全角スペース対応)
        s = ZenkakuConverter.ToHankakuBasic(s);     // 全角英数字→半角
        s = s.ToLowerInvariant();                   // 小文字にそろえる

        return s;
    }

    public static bool CodeEquals(string? left, string? right)
    {
        string l = NormalizeCodeToLower(left);
        string r = NormalizeCodeToLower(right);

        return l == r;
    }
}
C#

使い方の例です。

string? input = " AbC123  ";
string? master = "abc123";

if (CodeNormalizeUtil.CodeEquals(input, master))
{
    Console.WriteLine("コード一致");
}
else
{
    Console.WriteLine("コード不一致");
}
C#

ここまでやっておくと、

全角・半角
前後の空白
大文字・小文字

といった揺れを全部吸収したうえで比較できるようになります。
小文字変換は、この“正規化パイプライン”の最後の仕上げとして使うイメージです。


まとめ 「小文字変換ユーティリティ」は“ゆらぎを受け止めるためのクッション”

小文字変換は、大文字変換と対になる、基本だけど奥の深いテクニックです。

押さえておきたいポイントはこうです。

ToLower() はカルチャ依存なので、比較や検索には ToLowerInvariant() を使う。
null 安全な ToLowerSafe を用意しておくと、「null かもしれない文字列」を扱うときに毎回ビクビクしなくて済む。
メールアドレスや URL、キー文字列など、「大文字小文字を区別したくない」ものは、小文字にそろえて扱う設計がしやすい。
実務では、小文字変換単体ではなく、「トリム」「全角→半角」と組み合わせた“正規化パイプライン”の一部として使うと威力を発揮する。

ここまで理解できれば、「なんとなく ToLower している」状態から抜け出して、
「どこで、何のために、小文字にそろえるのか」を意図して設計できる C# ユーティリティを書けるようになっていきます。

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