C#で大文字・小文字を変換・判定・区別しない比較をする方法

はじめに

C#で文字列を扱うとき、「大文字に変換したい」「小文字かどうか判定したい」「大文字・小文字を区別せずに比較したい」という処理はよく登場します。

たとえば、次のような場面です。

C#
"abc"  "ABC" に変換したい
"A" が大文字か判定したい
"Admin" "admin" を同じ文字列として扱いたい
"README.TXT" ".txt" で終わるか判定したい

C#では、文字列全体を変換する場合は ToUpperToLower、1文字を判定する場合は char.IsUpperchar.IsLower、大文字・小文字を区別しない比較では StringComparison.OrdinalIgnoreCase などを使います。

ただし、単純に ToUpper()ToLower() で変換してから比較すると、カルチャの影響やパフォーマンス、null参照例外などで問題が起きることがあります。.NETの文字列比較では、用途に応じて StringComparison を明示することが推奨されています。Microsoft Learn

この記事では、C#で大文字・小文字を変換、判定、比較、検索する方法をサンプルコード付きで解説します。

1. C#で大文字・小文字を扱う基本

1-1. C#における文字列と文字の違い

C#で大文字・小文字を扱うときは、まず stringchar の違いを理解しておく必要があります。

string は文字列全体を表す型です。たとえば "Hello""ABC123"string です。

C#
string text = "Hello";

一方、char は1文字を表す型です。たとえば 'A''h'char です。

C#
char ch = 'A';

C#の string キーワードは System.String の別名で、文字列の作成、操作、比較に使う多くのメソッドが用意されています。また、C#の文字列は不変で、変換メソッドを呼び出しても元の文字列自体は変更されず、新しい文字列が返されます。Microsoft Learn

C#
string text = "hello";
string upper = text.ToUpper();

Console.WriteLine(text); // hello
Console.WriteLine(upper); // HELLO

text.ToUpper() を実行しても、text の中身が直接 "HELLO" に変わるわけではありません。変換後の値を使いたい場合は、戻り値を別の変数に代入する必要があります。

1-2. 大文字・小文字を扱う主な処理

C#で大文字・小文字を扱う処理は、大きく分けると次の4つです。

処理目的主なメソッド
変換大文字または小文字に変えるToUpper, ToLower
1文字の変換char を大文字・小文字に変えるchar.ToUpper, char.ToLower
判定大文字か小文字か調べるchar.IsUpper, char.IsLower
比較大文字・小文字を区別する、または無視するEquals, StringComparison
検索大文字・小文字を無視して含まれるか調べるContains, IndexOf, StartsWith, EndsWith

実務では、単に変換するだけでなく、「比較のために大文字・小文字を無視したい」というケースが多くあります。その場合は、変換してから比較するよりも、StringComparison.OrdinalIgnoreCase を使って比較する方法が基本です。

1-3. 変換・判定・比較で使うメソッド一覧

C#でよく使う大文字・小文字関連のメソッドは次のとおりです。

メソッド用途
string.ToUpper()文字列を大文字に変換
string.ToLower()文字列を小文字に変換
string.ToUpperInvariant()カルチャに依存せず大文字に変換
string.ToLowerInvariant()カルチャに依存せず小文字に変換
char.ToUpper(char)1文字を大文字に変換
char.ToLower(char)1文字を小文字に変換
char.IsUpper(char)1文字が大文字か判定
char.IsLower(char)1文字が小文字か判定
string.Equals(..., StringComparison.OrdinalIgnoreCase)大文字・小文字を無視して比較
IndexOf(..., StringComparison.OrdinalIgnoreCase)大文字・小文字を無視して検索
StartsWith(..., StringComparison.OrdinalIgnoreCase)大文字・小文字を無視して前方一致
EndsWith(..., StringComparison.OrdinalIgnoreCase)大文字・小文字を無視して後方一致

2. C#で文字列を大文字・小文字に変換する方法

2-1. ToUpperで文字列を大文字に変換する

文字列をすべて大文字に変換するには、ToUpper() を使います。

C#
string text = "hello csharp";
string result = text.ToUpper();

Console.WriteLine(result); // HELLO CSHARP

英字の小文字が大文字に変換されます。数字や記号、日本語など、大文字・小文字の概念がない文字は基本的にそのままです。

C#
string text = "abc123あいう!";
string result = text.ToUpper();

Console.WriteLine(result); // ABC123あいう!

入力値をコードや識別子として大文字に統一したい場合に便利です。

C#
string code = "abc-001";
code = code.ToUpper();

Console.WriteLine(code); // ABC-001

2-2. ToLowerで文字列を小文字に変換する

文字列をすべて小文字に変換するには、ToLower() を使います。

C#
string text = "HELLO CSHARP";
string result = text.ToLower();

Console.WriteLine(result); // hello csharp

メールアドレス、タグ、検索キーワードなどを小文字で統一したい場合に使われることがあります。

C#
string keyword = "CSharp";
string normalized = keyword.ToLower();

Console.WriteLine(normalized); // csharp

ただし、比較のためだけに ToLower() で変換するのはおすすめできません。大文字・小文字を区別せず比較したい場合は、後述する StringComparison.OrdinalIgnoreCase を使う方が適切です。

2-3. ToUpperInvariant・ToLowerInvariantとの違い

ToUpper()ToLower() は、現在のカルチャの影響を受けます。一方、ToUpperInvariant()ToLowerInvariant() は、インバリアントカルチャを使って変換します。

C#
string text = "hello";

Console.WriteLine(text.ToUpper()); // HELLO
Console.WriteLine(text.ToUpperInvariant()); // HELLO

英語の単純な文字列では結果が同じに見えることが多いですが、カルチャによって大文字・小文字の扱いが異なる文字では差が出る場合があります。ToLowerInvariant は、現在のカルチャに左右されない予測可能な変換が必要な場合に使うメソッドとして説明されています。Microsoft Learn

たとえば、プログラム内部のキー、コード、プロトコル名など、言語文化に依存させたくない値を正規化する場合は、ToUpperInvariant()ToLowerInvariant() を検討します。

C#
string key = "UserName";
string normalizedKey = key.ToLowerInvariant();

Console.WriteLine(normalizedKey); // username

2-4. 変換時に注意したいカルチャの影響

大文字・小文字の変換は、単なる英字変換だけではありません。言語によっては、同じ文字に見えても大文字・小文字の対応が異なることがあります。

そのため、次のように比較目的で変換するコードは避けた方が安全です。

C#
// 非推奨になりやすい書き方
if (a.ToLower() == b.ToLower())
{
Console.WriteLine("同じです");
}

この書き方には、主に次の問題があります。

  • 変換後の新しい文字列が生成される

  • nullの場合に例外が発生する

  • カルチャの影響を受ける可能性がある

  • 比較の意図がコードから読み取りにくい

比較したい場合は、次のように StringComparison を指定します。

C#
if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("同じです");
}

この方が「大文字・小文字を無視して比較する」という意図が明確です。

2-5. nullや空文字を扱うときの注意点

ToUpper()ToLower() はインスタンスメソッドなので、対象の文字列が null の場合は NullReferenceException が発生します。

C#
string text = null;

// 例外が発生する
string upper = text.ToUpper();

nullの可能性がある場合は、null条件演算子 ?. を使います。

C#
string text = null;
string upper = text?.ToUpper();

Console.WriteLine(upper == null); // True

nullを空文字として扱いたい場合は、null合体演算子 ?? を使います。

C#
string text = null;
string upper = (text ?? "").ToUpper();

Console.WriteLine(upper); // 空文字

空文字 "" に対して ToUpper()ToLower() を呼び出しても例外にはなりません。

C#
string text = "";
string result = text.ToUpper();

Console.WriteLine(result); // 空文字

3. C#で1文字の大文字・小文字を変換する方法

3-1. char.ToUpperで1文字を大文字に変換する

1文字だけを大文字に変換するには、char.ToUpper() を使います。

C#
char ch = 'a';
char result = char.ToUpper(ch);

Console.WriteLine(result); // A

char.ToUpper()char を受け取り、変換後の char を返します。

C#
char ch1 = 'b';
char ch2 = 'B';
char ch3 = '1';

Console.WriteLine(char.ToUpper(ch1)); // B
Console.WriteLine(char.ToUpper(ch2)); // B
Console.WriteLine(char.ToUpper(ch3)); // 1

すでに大文字の場合や、大文字・小文字の概念がない文字の場合は、基本的にそのまま返されます。

3-2. char.ToLowerで1文字を小文字に変換する

1文字だけを小文字に変換するには、char.ToLower() を使います。

C#
char ch = 'A';
char result = char.ToLower(ch);

Console.WriteLine(result); // a

複数の文字を1文字ずつ処理したい場合にも使えます。

C#
char[] chars = { 'A', 'B', 'C' };

for (int i = 0; i < chars.Length; i++)
{
chars[i] = char.ToLower(chars[i]);
}

Console.WriteLine(new string(chars)); // abc

3-3. 文字列内の特定の文字だけを変換する方法

文字列の先頭1文字だけを大文字にしたい場合は、char.ToUpper()Substring を組み合わせます。

C#
string text = "hello";

string result = char.ToUpper(text[0]) + text.Substring(1);

Console.WriteLine(result); // Hello

ただし、空文字の場合は text[0] で例外が発生するため、事前にチェックします。

C#
string Capitalize(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}

return char.ToUpper(text[0]) + text.Substring(1);
}

Console.WriteLine(Capitalize("hello")); // Hello
Console.WriteLine(Capitalize("")); // 空文字

特定の位置の文字だけを変換したい場合、string は不変なので直接変更できません。char[] に変換してから処理します。

C#
string text = "hello";
char[] chars = text.ToCharArray();

chars[1] = char.ToUpper(chars[1]);

string result = new string(chars);

Console.WriteLine(result); // hEllo

3-4. 文字列全体とcharの変換処理の使い分け

文字列全体を変換したい場合は、string.ToUpper()string.ToLower() を使います。

C#
string text = "hello";
string upper = text.ToUpper();

1文字だけを変換したい場合は、char.ToUpper()char.ToLower() を使います。

C#
char ch = 'h';
char upper = char.ToUpper(ch);

使い分けの目安は次のとおりです。

やりたいこと使うメソッド
文字列全体を大文字にするToUpper()
文字列全体を小文字にするToLower()
1文字だけ大文字にするchar.ToUpper()
1文字だけ小文字にするchar.ToLower()
先頭だけ大文字にするchar.ToUpper()Substring

4. C#で大文字・小文字を判定する方法

4-1. char.IsUpperで大文字か判定する

1文字が大文字かどうかを判定するには、char.IsUpper() を使います。

C#
char ch = 'A';

if (char.IsUpper(ch))
{
Console.WriteLine("大文字です");
}

実行結果は次のようになります。

大文字です

char.IsUpper は、指定したUnicode文字が大文字として分類されるかどうかを判定します。Microsoft Learn

C#
Console.WriteLine(char.IsUpper('A')); // True
Console.WriteLine(char.IsUpper('a')); // False
Console.WriteLine(char.IsUpper('1')); // False
Console.WriteLine(char.IsUpper('あ')); // False

4-2. char.IsLowerで小文字か判定する

1文字が小文字かどうかを判定するには、char.IsLower() を使います。

C#
char ch = 'a';

if (char.IsLower(ch))
{
Console.WriteLine("小文字です");
}

char.IsLower() は、小文字として分類される文字の場合に true を返します。

C#
Console.WriteLine(char.IsLower('a')); // True
Console.WriteLine(char.IsLower('A')); // False
Console.WriteLine(char.IsLower('1')); // False
Console.WriteLine(char.IsLower('あ')); // False

4-3. string内に大文字・小文字が含まれるか判定する

文字列内に大文字が含まれるかを判定するには、1文字ずつ調べます。

C#
string text = "Hello";

bool hasUpper = false;

foreach (char ch in text)
{
if (char.IsUpper(ch))
{
hasUpper = true;
break;
}
}

Console.WriteLine(hasUpper); // True

小文字が含まれるかを判定する場合は、char.IsLower() を使います。

C#
string text = "HELLo";

bool hasLower = false;

foreach (char ch in text)
{
if (char.IsLower(ch))
{
hasLower = true;
break;
}
}

Console.WriteLine(hasLower); // True

4-4. LINQを使って大文字・小文字を判定する

LINQの Any() を使うと、より短く書けます。

C#
using System.Linq;

string text = "Hello";

bool hasUpper = text.Any(char.IsUpper);
bool hasLower = text.Any(char.IsLower);

Console.WriteLine(hasUpper); // True
Console.WriteLine(hasLower); // True

すべて大文字かどうかを判定したい場合は、All() を使います。

C#
using System.Linq;

string text = "ABC";

bool allUpper = text.All(ch => !char.IsLetter(ch) || char.IsUpper(ch));

Console.WriteLine(allUpper); // True

この例では、数字や記号を含む場合も考慮して、英字などの文字だけを判定対象にしています。

C#
string code = "ABC-123";

bool allLettersUpper = code.All(ch => !char.IsLetter(ch) || char.IsUpper(ch));

Console.WriteLine(allLettersUpper); // True

4-5. 英字以外の文字が含まれる場合の注意点

char.IsUpper()char.IsLower() は、英字の A-Za-z だけを見るメソッドではありません。Unicode上の大文字・小文字カテゴリに基づいて判定します。

そのため、英字だけを対象にしたい場合は、範囲を明示する方法もあります。

C#
bool IsAsciiUpper(char ch)
{
return ch >= 'A' && ch <= 'Z';
}

bool IsAsciiLower(char ch)
{
return ch >= 'a' && ch <= 'z';
}

Console.WriteLine(IsAsciiUpper('A')); // True
Console.WriteLine(IsAsciiUpper('あ')); // False

ID、コード、ファイル拡張子など、ASCIIの英数字だけを前提にする場合は、このように範囲を限定した判定の方が意図に合うこともあります。

5. C#で大文字・小文字を区別しない比較をする方法

5-1. string.Equalsで大文字・小文字を無視して比較する

C#で大文字・小文字を区別せずに文字列を比較する場合は、string.EqualsStringComparison.OrdinalIgnoreCase を指定するのが基本です。

C#
string a = "Hello";
string b = "hello";

bool result = string.Equals(a, b, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

StringComparison を指定できる Equals は、比較方法を明示できるため、コードの意図がわかりやすくなります。StringComparison は、現在のカルチャ、インバリアントカルチャ、序数比較、さらに大文字・小文字を無視するかどうかを指定するための列挙型です。Microsoft Learn

5-2. StringComparison.OrdinalIgnoreCaseを使う方法

StringComparison.OrdinalIgnoreCase は、カルチャに依存しない序数比較を行い、大文字・小文字を無視します。

C#
string input = "admin";

if (string.Equals(input, "ADMIN", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("管理者です");
}

プログラム内部の識別子、キー、コード、拡張子、コマンド名などを比較する場合は、OrdinalIgnoreCase が適していることが多いです。.NETのドキュメントでも、プログラムによって生成された文字列やパス、ファイル名などの大文字・小文字を無視した比較には StringComparer.OrdinalIgnoreCase が適していると説明されています。Microsoft Learn

5-3. CurrentCultureIgnoreCaseとの違い

StringComparison.CurrentCultureIgnoreCase は、現在のカルチャの規則に従い、大文字・小文字を無視して比較します。

C#
string a = "hello";
string b = "HELLO";

bool result = string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

Console.WriteLine(result); // True

CurrentCultureIgnoreCase は、ユーザーに表示される自然言語の文字列を比較する場合に向いています。たとえば、画面に表示する名前、単語、文章などをユーザーの言語文化に合わせて比較したい場合です。

一方、ID、設定キー、ファイル拡張子、URLの一部、プロトコル名など、言語文化に依存させたくない値では OrdinalIgnoreCase を使う方が適切です。

比較方法特徴向いている用途
OrdinalIgnoreCaseカルチャに依存しないID、キー、コード、拡張子
CurrentCultureIgnoreCase現在のカルチャに依存するユーザー向けの自然言語
InvariantCultureIgnoreCaseインバリアントカルチャに基づく一部の固定的な言語処理

5-4. ==演算子との違い

C#では、文字列を == で比較できます。

C#
string a = "Hello";
string b = "hello";

Console.WriteLine(a == b); // False

== は値の比較として使えますが、大文字・小文字を区別します。また、StringComparison.OrdinalIgnoreCase のような比較方法を指定できません。

そのため、大文字・小文字を区別しない比較では、== ではなく string.Equals() を使います。

C#
string a = "Hello";
string b = "hello";

Console.WriteLine(string.Equals(a, b, StringComparison.OrdinalIgnoreCase)); // True

5-5. 比較処理でおすすめの書き方

大文字・小文字を区別しない比較でおすすめなのは、次の書き方です。

C#
if (string.Equals(value, "target", StringComparison.OrdinalIgnoreCase))
{
// 一致した場合の処理
}

この書き方には、次のメリットがあります。

  • 大文字・小文字を無視する意図が明確

  • 余計な文字列変換が不要

  • nullに比較的強い

  • カルチャ依存の問題を避けやすい

たとえば、コマンド名を判定する場合は次のように書けます。

C#
string command = "START";

if (string.Equals(command, "start", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("開始します");
}

比較のために次のような書き方をするのは避けましょう。

C#
// 非推奨
if (command.ToLower() == "start")
{
Console.WriteLine("開始します");
}

6. C#で大文字・小文字を区別しない検索をする方法

6-1. Containsで大文字・小文字を無視して検索する

.NET Core 2.1以降では、ContainsStringComparison を指定できます。Contains(String, StringComparison) は、指定した比較規則で文字列が含まれるかを判定するオーバーロードです。Microsoft Learn

C#
string text = "Hello CSharp";
string keyword = "csharp";

bool result = text.Contains(keyword, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

通常の Contains は大文字・小文字を区別します。

C#
string text = "Hello CSharp";

Console.WriteLine(text.Contains("csharp")); // False

大文字・小文字を無視したい場合は、次のように書きます。

C#
Console.WriteLine(text.Contains("csharp", StringComparison.OrdinalIgnoreCase)); // True

6-2. IndexOfで大文字・小文字を無視して検索する

IndexOf でも StringComparison.OrdinalIgnoreCase を指定できます。

C#
string text = "Hello CSharp";
string keyword = "csharp";

int index = text.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);

if (index >= 0)
{
Console.WriteLine($"見つかりました: {index}");
}

IndexOf は、見つかった位置を0始まりのインデックスで返します。見つからない場合は -1 を返します。

C#
string text = "Hello CSharp";

Console.WriteLine(text.IndexOf("hello", StringComparison.OrdinalIgnoreCase)); // 0
Console.WriteLine(text.IndexOf("java", StringComparison.OrdinalIgnoreCase)); // -1

.NET Frameworkなど、ContainsStringComparison を指定できない環境では、IndexOf(..., StringComparison.OrdinalIgnoreCase) >= 0 を使う方法が定番です。

C#
bool contains = text.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0;

6-3. StartsWith・EndsWithで区別しない判定をする

先頭が特定の文字列で始まるかを判定するには、StartsWith を使います。

C#
string text = "HelloWorld";

bool result = text.StartsWith("hello", StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

末尾が特定の文字列で終わるかを判定するには、EndsWith を使います。

C#
string fileName = "README.TXT";

bool isTextFile = fileName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase);

Console.WriteLine(isTextFile); // True

EndsWith(String, StringComparison) は、指定した比較方法で文字列の末尾が一致するかを判定できます。Microsoft Learn

ファイル拡張子の判定では、大文字・小文字の揺れがよくあるため、OrdinalIgnoreCase を指定すると実用的です。

C#
string fileName = "image.PNG";

if (fileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("PNG画像です");
}

6-4. 配列やList内を大文字・小文字を無視して検索する

配列や List<string> の中から、大文字・小文字を無視して一致する要素を探す場合は、LINQの Anystring.Equals を組み合わせます。

C#
using System;
using System.Collections.Generic;
using System.Linq;

List<string> names = new List<string> { "Alice", "Bob", "Charlie" };

bool exists = names.Any(name =>
string.Equals(name, "alice", StringComparison.OrdinalIgnoreCase));

Console.WriteLine(exists); // True

該当する要素を取得したい場合は、FirstOrDefault を使います。

C#
string found = names.FirstOrDefault(name =>
string.Equals(name, "bob", StringComparison.OrdinalIgnoreCase));

Console.WriteLine(found); // Bob

リスト内に同じ値を大文字・小文字違いで重複登録したくない場合は、HashSet<string>StringComparer.OrdinalIgnoreCase を指定する方法もあります。

C#
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

set.Add("Apple");
set.Add("apple");

Console.WriteLine(set.Count); // 1

6-5. Dictionaryで大文字・小文字を区別しないキー比較をする

Dictionary<string, TValue> のキー比較で大文字・小文字を無視したい場合は、作成時に StringComparer.OrdinalIgnoreCase を指定します。

C#
var users = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

users["Alice"] = 1;

Console.WriteLine(users.ContainsKey("alice")); // True
Console.WriteLine(users["ALICE"]); // 1

Dictionary<TKey,TValue> には、キーの比較に使う IEqualityComparer<TKey> を受け取るコンストラクターがあります。Microsoft Learn

後から比較方法を変更することはできないため、大文字・小文字を区別しない辞書にしたい場合は、最初に指定しておくことが重要です。

C#
var settings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["Theme"] = "Dark",
["Language"] = "ja"
};

Console.WriteLine(settings["theme"]); // Dark
Console.WriteLine(settings["LANGUAGE"]); // ja

7. 大文字・小文字を区別する比較との使い分け

7-1. 区別する比較が必要なケース

すべての比較で大文字・小文字を無視すればよいわけではありません。大文字・小文字の違いに意味がある場合は、区別する比較が必要です。

たとえば、次のようなケースです。

  • パスワード

  • トークン

  • APIキー

  • 暗号化された値

  • 大文字・小文字を区別する仕様のID

  • プログラミング言語の識別子

  • 一部の外部サービスのキー

パスワードで "Password""password" を同じ扱いにしてしまうと、セキュリティ上の問題につながる可能性があります。

C#
string inputPassword = "Password";
string savedPassword = "password";

bool match = inputPassword == savedPassword;

Console.WriteLine(match); // False

このようなケースでは、大文字・小文字を区別する比較を使います。

7-2. 区別しない比較が適しているケース

大文字・小文字を区別しない比較が適しているのは、ユーザー入力の揺れを許容したい場合です。

たとえば、次のようなケースです。

  • コマンド名

  • 検索キーワード

  • ファイル拡張子

  • メールアドレスの比較

  • 設定キー

  • タグ名

  • ユーザーが入力するコード

C#
string input = "yes";

if (string.Equals(input, "YES", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("同意しました");
}

ユーザーが "yes""YES""Yes" のどれを入力しても同じ扱いにできます。

7-3. ID・コード・ファイル名・ユーザー入力での考え方

大文字・小文字を区別するかどうかは、データの種類ごとに決めるべきです。

データ比較方法の目安
パスワード区別する
認証トークン区別する
商品コード仕様次第
ファイル拡張子区別しないことが多い
コマンド入力区別しないことが多い
検索キーワード区別しないことが多い
表示名カルチャを考慮する場合がある
設定キーOrdinalIgnoreCase が使いやすい

たとえば商品コードでは、仕様として "abc001""ABC001" を同じコードとして扱うのか、別のコードとして扱うのかを明確にする必要があります。

C#
string code1 = "abc001";
string code2 = "ABC001";

bool sameCode = string.Equals(code1, code2, StringComparison.OrdinalIgnoreCase);

仕様上同じなら OrdinalIgnoreCase、別物なら通常の比較を使います。

7-4. セキュリティや認証処理での注意点

セキュリティに関わる文字列では、大文字・小文字を安易に無視してはいけません。

特に、次の値は原則として完全一致で扱います。

  • パスワード

  • アクセストークン

  • リフレッシュトークン

  • 署名値

  • ハッシュ値

  • ランダムな認証コード

C#
bool isValid = string.Equals(inputToken, storedToken, StringComparison.Ordinal);

大文字・小文字を無視すると、本来一致しないはずの値を一致と判定してしまう可能性があります。認証や認可に関わる処理では、仕様を確認したうえで、必要な比較方法を明示しましょう。

8. C#の大文字・小文字処理でよくあるエラーと対策

8-1. ToUpperやToLowerで比較してはいけないケース

よくある書き方に、両方の文字列を小文字にしてから比較する方法があります。

C#
// 避けたい書き方
if (a.ToLower() == b.ToLower())
{
Console.WriteLine("一致");
}

一見わかりやすいですが、比較目的ではおすすめできません。

理由は次のとおりです。

  • 変換後の文字列が生成される

  • nullの場合に例外になる

  • カルチャの影響を受ける

  • 比較方法が明示されない

代わりに、次のように書きます。

C#
if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("一致");
}

検索の場合も同様です。

C#
// 避けたい書き方
bool contains = text.ToLower().Contains(keyword.ToLower());

次のように書く方が適切です。

C#
bool contains = text.Contains(keyword, StringComparison.OrdinalIgnoreCase);

8-2. カルチャ差による想定外の比較結果

大文字・小文字の変換や比較は、カルチャによって結果が変わることがあります。

たとえば、ユーザーの表示言語に合わせた自然言語の比較では CurrentCultureIgnoreCase が適切な場合があります。一方、プログラム内部の識別子や設定キーでは、カルチャに依存しない OrdinalIgnoreCase の方が安全です。

C#
// プログラム内部のキー比較
bool sameKey = string.Equals(key1, key2, StringComparison.OrdinalIgnoreCase);

// ユーザーに表示する自然言語の比較
bool sameWord = string.Equals(word1, word2, StringComparison.CurrentCultureIgnoreCase);

どちらを使うか迷った場合は、「その文字列は人間の言語として比較したいのか」「プログラム上の記号として比較したいのか」を基準にします。

8-3. null参照例外を防ぐ書き方

次のようなコードは、inputnull の場合に例外になります。

C#
if (input.ToLower() == "yes")
{
Console.WriteLine("YESです");
}

安全に書くなら、string.Equals を使います。

C#
if (string.Equals(input, "yes", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("YESです");
}

この書き方なら、inputnull でも例外になりません。

C#
string input = null;

bool result = string.Equals(input, "yes", StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // False

メソッド呼び出しの対象がnullになる可能性がある場合は、null条件演算子も使えます。

C#
string text = null;

bool result = text?.Contains("abc", StringComparison.OrdinalIgnoreCase) == true;

Console.WriteLine(result); // False

8-4. パフォーマンスを意識した比較方法

比較のたびに ToUpper()ToLower() を呼び出すと、新しい文字列が生成されます。大量のデータを処理する場合は、無駄なメモリ確保や処理時間につながります。

C#
// 大量データでは非効率になりやすい
items.Where(x => x.ToLower() == keyword.ToLower());

比較メソッドに StringComparison.OrdinalIgnoreCase を指定すれば、変換用の文字列を作らずに比較できます。

C#
var matched = items.Where(x =>
string.Equals(x, keyword, StringComparison.OrdinalIgnoreCase));

検索でも同じです。

C#
var matched = items.Where(x =>
x.Contains(keyword, StringComparison.OrdinalIgnoreCase));

DictionaryHashSet では、最初から StringComparer.OrdinalIgnoreCase を指定すると、検索や重複判定を効率よく行えます。

C#
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

set.Add("csharp");

Console.WriteLine(set.Contains("CSHARP")); // True

8-5. 日本語や記号が混在する文字列の扱い

日本語、数字、記号には、大文字・小文字の概念がないものが多くあります。

C#
string text = "C#入門-ABC123";

Console.WriteLine(text.ToLower()); // c#入門-abc123

この場合、英字部分だけが小文字になります。日本語や記号はそのままです。

ただし、全角英字や特殊なUnicode文字が混在する場合は、単純なASCIIの大文字・小文字変換だけでは期待通りにならないことがあります。

C#
string text = "ABC abc";
Console.WriteLine(text.ToLower());

全角・半角の統一、ひらがな・カタカナの統一、濁点の扱いなどは、大文字・小文字とは別の正規化処理として考える必要があります。

9. 実用的なサンプルコード集

9-1. 入力値を大文字に統一するサンプル

ユーザーが入力したコードを大文字に統一する例です。

C#
Console.Write("商品コードを入力してください: ");
string input = Console.ReadLine();

string code = input?.Trim().ToUpperInvariant();

Console.WriteLine($"登録コード: {code}");

Trim() で前後の空白を削除し、ToUpperInvariant() でカルチャに依存しない大文字変換を行っています。

nullを空文字にしたい場合は、次のようにします。

C#
string code = (input ?? "").Trim().ToUpperInvariant();

9-2. メールアドレスを大文字・小文字を無視して比較するサンプル

メールアドレスの比較では、大文字・小文字の違いを無視したいケースがあります。

C#
string registeredEmail = "user@example.com";
string inputEmail = "USER@example.com";

bool same = string.Equals(
registeredEmail,
inputEmail,
StringComparison.OrdinalIgnoreCase);

Console.WriteLine(same); // True

入力前後の空白も無視したい場合は、Trim() と組み合わせます。

C#
string registeredEmail = "user@example.com";
string inputEmail = " USER@example.com ";

bool same = string.Equals(
registeredEmail,
inputEmail?.Trim(),
StringComparison.OrdinalIgnoreCase);

Console.WriteLine(same); // True

9-3. 検索キーワードを大文字・小文字を無視して判定するサンプル

文章の中にキーワードが含まれるかを、大文字・小文字を無視して検索します。

C#
string text = "C# is a modern programming language.";
string keyword = "PROGRAMMING";

bool contains = text.Contains(keyword, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(contains); // True

.NET Frameworkなどで ContainsStringComparison を指定できない場合は、IndexOf を使います。

C#
bool contains = text.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0;

9-4. ファイル拡張子を大文字・小文字を無視して判定するサンプル

ファイル拡張子は、.txt.TXT.Txt のように表記が揺れることがあります。

C#
string fileName = "report.PDF";

if (fileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("PDFファイルです");
}

複数の拡張子を判定する場合は、配列と Any を使えます。

C#
using System;
using System.Linq;

string fileName = "photo.JPG";

string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif" };

bool isImage = imageExtensions.Any(ext =>
fileName.EndsWith(ext, StringComparison.OrdinalIgnoreCase));

Console.WriteLine(isImage); // True

9-5. ListやDictionaryで大文字・小文字を無視するサンプル

List<string> で大文字・小文字を無視して検索する例です。

C#
using System;
using System.Collections.Generic;
using System.Linq;

var languages = new List<string> { "CSharp", "Java", "Python" };

bool exists = languages.Any(x =>
string.Equals(x, "csharp", StringComparison.OrdinalIgnoreCase));

Console.WriteLine(exists); // True

Dictionary のキーを大文字・小文字を無視して扱う例です。

C#
using System;
using System.Collections.Generic;

var scores = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

scores["Alice"] = 90;

Console.WriteLine(scores.ContainsKey("alice")); // True
Console.WriteLine(scores["ALICE"]); // 90

Dictionary を作成した後に比較方法を変更することはできないため、最初に StringComparer.OrdinalIgnoreCase を指定するのがポイントです。

10. C#の大文字・小文字処理に関するよくある質問

10-1. ToUpperとToUpperInvariantはどちらを使うべきか

ユーザーに表示する自然言語の文字列を、現在のカルチャに合わせて変換したい場合は ToUpper() を使います。

一方、プログラム内部のキー、コード、識別子、ファイル拡張子など、カルチャに依存させたくない値を変換する場合は ToUpperInvariant() を使うのが無難です。

C#
string key = "content-type";
string normalized = key.ToUpperInvariant();

Console.WriteLine(normalized); // CONTENT-TYPE

ただし、比較のためだけに大文字へ変換する必要はありません。比較には StringComparison.OrdinalIgnoreCase を使いましょう。

C#
bool same = string.Equals(a, b, StringComparison.OrdinalIgnoreCase);

10-2. 大文字・小文字を区別しない比較で最もおすすめの方法は何か

プログラム内部の文字列比較では、次の書き方がおすすめです。

C#
string.Equals(a, b, StringComparison.OrdinalIgnoreCase)

たとえば、コマンド、キー、コード、拡張子などの比較に向いています。

C#
if (string.Equals(command, "start", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("開始");
}

自然言語として比較したい場合は、CurrentCultureIgnoreCase を検討します。

C#
string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase)

10-3. ContainsでOrdinalIgnoreCaseは使えるのか

使えます。現在の.NETでは、ContainsStringComparison.OrdinalIgnoreCase を指定できます。

C#
string text = "Hello World";

bool result = text.Contains("hello", StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

ただし、古い.NET Frameworkでは Contains(string, StringComparison) が使えないため、次のように IndexOf を使います。

C#
bool result = text.IndexOf("hello", StringComparison.OrdinalIgnoreCase) >= 0;

10-4. 日本語文字列でも大文字・小文字の変換は必要か

日本語のひらがな、カタカナ、漢字には、通常の英字のような大文字・小文字の区別はありません。そのため、日本語だけの文字列であれば ToUpper()ToLower() の効果はほとんどありません。

C#
string text = "こんにちは";
Console.WriteLine(text.ToUpper()); // こんにちは

ただし、日本語の中に英字が混ざっている場合は、英字部分だけ変換されます。

C#
string text = "C#入門";
Console.WriteLine(text.ToLower()); // c#入門

日本語検索で問題になりやすいのは、大文字・小文字よりも、全角・半角、ひらがな・カタカナ、濁点、長音などの違いです。これらは別途、正規化処理を検討する必要があります。

10-5. 大文字・小文字を無視した正規表現の書き方

正規表現で大文字・小文字を無視したい場合は、RegexOptions.IgnoreCase を使います。

C#
using System.Text.RegularExpressions;

string text = "Hello CSharp";

bool match = Regex.IsMatch(text, "csharp", RegexOptions.IgnoreCase);

Console.WriteLine(match); // True

カルチャに依存しない比較にしたい場合は、RegexOptions.CultureInvariant も組み合わせます。

C#
bool match = Regex.IsMatch(
text,
"csharp",
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

メールアドレス、コード、タグ、識別子など、自然言語ではなくプログラム上の値を扱う場合は、カルチャの影響を避けることも検討しましょう。

まとめ

C#で大文字・小文字を扱う処理には、変換、判定、比較、検索があります。

文字列全体を大文字にする場合は ToUpper()、小文字にする場合は ToLower() を使います。カルチャに依存しない変換をしたい場合は、ToUpperInvariant()ToLowerInvariant() を使います。

C#
string upper = text.ToUpperInvariant();
string lower = text.ToLowerInvariant();

1文字だけを変換する場合は、char.ToUpper()char.ToLower() を使います。

C#
char upperChar = char.ToUpper('a');
char lowerChar = char.ToLower('A');

大文字かどうか、小文字かどうかを判定する場合は、char.IsUpper()char.IsLower() を使います。

C#
bool isUpper = char.IsUpper('A');
bool isLower = char.IsLower('a');

大文字・小文字を区別しない比較では、ToUpper()ToLower() で変換してから比較するのではなく、StringComparison.OrdinalIgnoreCase を指定するのが基本です。

C#
bool same = string.Equals(a, b, StringComparison.OrdinalIgnoreCase);

検索では、ContainsIndexOfStartsWithEndsWithStringComparison.OrdinalIgnoreCase を指定します。

C#
text.Contains(keyword, StringComparison.OrdinalIgnoreCase);
text.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
text.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
text.EndsWith(suffix, StringComparison.OrdinalIgnoreCase);

List や配列では Anystring.Equals を組み合わせ、DictionaryHashSet では StringComparer.OrdinalIgnoreCase を指定すると、大文字・小文字を無視した検索やキー比較ができます。

C#
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

C#で大文字・小文字を扱うときは、「変換したいのか」「判定したいのか」「比較したいのか」「検索したいのか」を分けて考えることが重要です。特に比較や検索では、カルチャやnull、パフォーマンスの問題を避けるために、StringComparison.OrdinalIgnoreCase を明示して書くようにしましょう。