C# IndexOfの使い方を初心者向けに解説|文字列・List・配列の検索、戻り値-1、Containsとの違いまで

はじめに

C#で文字列や配列、Listの中から「特定の文字や値がどこにあるか」を調べたいときに使うのがIndexOfです。

たとえば、次のような場面で役立ちます。

C#
string text = "Hello C#";
int index = text.IndexOf("C#");

Console.WriteLine(index); // 6

IndexOfは、検索した文字列や要素が見つかった位置をint型で返します。見つからなかった場合は-1を返すため、初心者のうちはこの戻り値の扱いでつまずきやすいです。

この記事では、C#のIndexOfの基本から、文字列・List・配列での使い方、戻り値-1の意味、Containsとの違い、実践的な使い方まで初心者向けに解説します。

1. C#のIndexOfとは?検索位置を取得できる基本メソッド

C#のIndexOfは、文字列やコレクションの中から指定した値を探し、その位置を取得するためのメソッドです。

「含まれているかどうか」だけでなく、「何番目にあるのか」を知りたいときに使います。

1-1. IndexOfでできること:文字列・List・配列から要素の位置を探す

IndexOfは、主に次のような対象で使われます。

C#
// 文字列
string text = "apple";
int index1 = text.IndexOf("p");

// List
List<string> fruits = new List<string> { "apple", "banana", "orange" };
int index2 = fruits.IndexOf("banana");

// 配列
string[] names = { "田中", "佐藤", "鈴木" };
int index3 = Array.IndexOf(names, "佐藤");

文字列では文字部分文字列を検索できます。

List<T>では、リスト内の要素を検索できます。

配列では、Array.IndexOfを使って要素の位置を検索します。

1-2. IndexOfの戻り値は「0から始まるインデックス」

IndexOfの戻り値は、見つかった位置を表すインデックスです。

C#のインデックスは0から始まります。

C#
string text = "abcdef";

Console.WriteLine(text.IndexOf("a")); // 0
Console.WriteLine(text.IndexOf("c")); // 2
Console.WriteLine(text.IndexOf("f")); // 5

aは1文字目ですが、インデックスとしては0です。

初心者のうちは「1番目だから1」と考えてしまいがちですが、C#では先頭の位置は0です。

1-3. 見つからない場合は-1が返る

検索した文字や値が見つからなかった場合、IndexOf-1を返します。

C#
string text = "apple";

int index = text.IndexOf("z");

Console.WriteLine(index); // -1

-1は「見つからなかった」という意味です。

この-1を確認せずにSubstringRemoveなどへ渡すと、例外が発生することがあります。

1-4. IndexOfを使うべき場面と初心者がつまずきやすいポイント

IndexOfは、次のような場面で使うと便利です。

C#
string email = "sample@example.com";
int atIndex = email.IndexOf("@");

if (atIndex != -1)
{
Console.WriteLine("@の位置: " + atIndex);
}

たとえば、メールアドレスの@の位置を調べたり、特定の文字より前後を切り出したり、List内の要素を更新したりするときに使えます。

初心者がつまずきやすいポイントは次の3つです。

C#
// 1. 見つからないと -1 が返る
// 2. 先頭のインデックスは 0
// 3. 大文字・小文字は基本的に区別される

特に0-1の違いは重要です。

0は「先頭で見つかった」という意味であり、「見つからなかった」ではありません。

2. 文字列でIndexOfを使う方法

文字列でIndexOfを使うと、指定した文字や単語が文字列のどの位置にあるかを調べられます。

2-1. 文字列内の文字を検索する基本構文

文字列内の1文字を検索する基本構文は次のとおりです。

C#
文字列.IndexOf(検索する文字)

例を見てみましょう。

C#
string text = "programming";

int index = text.IndexOf('g');

Console.WriteLine(index); // 3

programmingの中で最初にgが出てくる位置はインデックス3です。

文字を検索する場合は、'g'のようにシングルクォーテーションを使います。

2-2. 文字列内の単語・部分文字列を検索する方法

単語や複数文字の部分文字列を検索する場合は、ダブルクォーテーションを使います。

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

int index = text.IndexOf("programming");

Console.WriteLine(index); // 8

この例では、programmingという文字列がインデックス8の位置から始まっているため、戻り値は8になります。

見つからない場合は-1です。

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

int index = text.IndexOf("Java");

Console.WriteLine(index); // -1

2-3. 検索開始位置を指定して途中から探す方法

IndexOfでは、検索を始める位置を指定できます。

C#
string text = "apple apple";

int index = text.IndexOf("apple", 1);

Console.WriteLine(index); // 6

この例では、インデックス1から検索を開始しています。

先頭のappleはインデックス0から始まるため検索対象から外れ、2つ目のappleが見つかります。

C#
string text = "banana";

int first = text.IndexOf("a");
int second = text.IndexOf("a", first + 1);

Console.WriteLine(first); // 1
Console.WriteLine(second); // 3

同じ文字が複数ある場合に、2回目以降の出現位置を探すときに便利です。

2-4. 検索範囲を指定して探す方法

検索開始位置に加えて、検索する文字数を指定することもできます。

C#
string text = "abcdefg";

int index = text.IndexOf("e", 2, 4);

Console.WriteLine(index); // 4

この例では、インデックス2から4文字分、つまりcdefの範囲でeを検索しています。

構文は次のようになります。

C#
文字列.IndexOf(検索する文字列, 開始位置, 検索する文字数)

範囲外の開始位置や文字数を指定すると例外になる場合があるため、文字列の長さを確認してから使うと安全です。

C#
string text = "abcdefg";

int startIndex = 2;
int count = 4;

if (startIndex >= 0 && startIndex + count <= text.Length)
{
int index = text.IndexOf("e", startIndex, count);
Console.WriteLine(index);
}

2-5. 大文字・小文字を区別せずに検索する方法

通常、IndexOfは大文字・小文字を区別します。

C#
string text = "Hello C#";

Console.WriteLine(text.IndexOf("hello")); // -1

Hellohelloは異なる文字列として扱われるため、見つかりません。

大文字・小文字を区別せずに検索したい場合は、StringComparison.OrdinalIgnoreCaseを指定します。

C#
string text = "Hello C#";

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

Console.WriteLine(index); // 0

実務では、英字を含む検索ではこの書き方がよく使われます。

C#
string fileName = "Report.PDF";

if (fileName.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) != -1)
{
Console.WriteLine("PDFファイルです");
}

2-6. 日本語文字列でもIndexOfは使える?

日本語文字列でもIndexOfは使えます。

C#
string text = "今日はいい天気です";

int index = text.IndexOf("天気");

Console.WriteLine(index); // 5

C#の文字列は日本語も扱えるため、英数字と同じように検索できます。

C#
string message = "エラーが発生しました";

if (message.IndexOf("エラー") != -1)
{
Console.WriteLine("エラーメッセージです");
}

ただし、全角・半角の違いや、見た目が似ている文字の違いには注意が必要です。

C#
string text = "ABC";

Console.WriteLine(text.IndexOf("ABC")); // -1

ABCは全角、ABCは半角なので一致しません。

必要に応じて、検索前に文字列を正規化したり、空白を取り除いたりするとよいでしょう。

3. ListでIndexOfを使う方法

List<T>でもIndexOfを使えます。

List内の要素を検索し、最初に見つかった位置を取得できます。

3-1. List<T>.IndexOfの基本構文

List<T>.IndexOfの基本構文は次のとおりです。

C#
list.IndexOf(検索する要素)

例を見てみましょう。

C#
List<string> fruits = new List<string>
{
"apple",
"banana",
"orange"
};

int index = fruits.IndexOf("banana");

Console.WriteLine(index); // 1

bananaはListの2番目の要素ですが、インデックスは1です。

3-2. List内の文字列・数値の位置を取得する例

文字列のListでは、次のように使えます。

C#
List<string> names = new List<string>
{
"田中",
"佐藤",
"鈴木"
};

int index = names.IndexOf("佐藤");

Console.WriteLine(index); // 1

数値のListでも同じように使えます。

C#
List<int> scores = new List<int>
{
80,
95,
70,
100
};

int index = scores.IndexOf(70);

Console.WriteLine(index); // 2

存在しない値を検索すると-1が返ります。

C#
List<int> scores = new List<int> { 80, 95, 70 };

int index = scores.IndexOf(60);

Console.WriteLine(index); // -1

3-3. 同じ値が複数ある場合は最初の位置だけ返る

List内に同じ値が複数ある場合、IndexOfは最初に見つかった位置だけを返します。

C#
List<string> items = new List<string>
{
"A",
"B",
"A",
"C"
};

int index = items.IndexOf("A");

Console.WriteLine(index); // 0

2つ目のAはインデックス2にありますが、IndexOfが返すのは最初のAの位置である0です。

すべての位置を取得したい場合は、ループを使って調べます。

C#
List<string> items = new List<string> { "A", "B", "A", "C" };

for (int i = 0; i < items.Count; i++)
{
if (items[i] == "A")
{
Console.WriteLine(i);
}
}

3-4. 検索開始位置や範囲を指定して探す方法

List<T>.IndexOfでも、検索開始位置を指定できます。

C#
List<string> items = new List<string>
{
"A",
"B",
"A",
"C"
};

int index = items.IndexOf("A", 1);

Console.WriteLine(index); // 2

この例では、インデックス1から検索しているため、最初のAは対象外になり、2つ目のAが見つかります。

検索範囲を指定することもできます。

C#
List<string> items = new List<string>
{
"A",
"B",
"A",
"C",
"A"
};

int index = items.IndexOf("A", 1, 3);

Console.WriteLine(index); // 2

この場合、インデックス1から3個分、つまりB, A, Cの範囲で検索します。

3-5. 自作クラス・オブジェクトを検索するときの注意点

自作クラスをListに入れてIndexOfで検索する場合は注意が必要です。

C#
class User
{
public string Name { get; set; }
}

次のコードを見てください。

C#
List<User> users = new List<User>
{
new User { Name = "田中" },
new User { Name = "佐藤" }
};

User target = new User { Name = "佐藤" };

int index = users.IndexOf(target);

Console.WriteLine(index); // -1

Nameが同じでも、別のインスタンスとして作られたオブジェクトは一致しないため、-1になります。

このような場合は、FindIndexを使うと分かりやすいです。

C#
List<User> users = new List<User>
{
new User { Name = "田中" },
new User { Name = "佐藤" }
};

int index = users.FindIndex(user => user.Name == "佐藤");

Console.WriteLine(index); // 1

または、クラス側でEqualsを適切に実装する方法もあります。

初心者の場合は、条件で探せるFindIndexを使うほうが理解しやすいでしょう。

4. 配列でIndexOfを使う方法

配列の場合は、文字列やListとは書き方が少し異なります。

配列ではArray.IndexOfを使います。

4-1. Array.IndexOfの基本構文

配列での基本構文は次のとおりです。

C#
Array.IndexOf(配列, 検索する要素)

例を見てみましょう。

C#
string[] fruits = { "apple", "banana", "orange" };

int index = Array.IndexOf(fruits, "banana");

Console.WriteLine(index); // 1

Listの場合はfruits.IndexOf("banana")でしたが、配列ではArray.IndexOf(fruits, "banana")と書きます。

4-2. 文字列配列から要素の位置を取得する例

文字列配列から要素の位置を取得する例です。

C#
string[] names = { "田中", "佐藤", "鈴木" };

int index = Array.IndexOf(names, "鈴木");

Console.WriteLine(index); // 2

見つからない場合は-1です。

C#
string[] names = { "田中", "佐藤", "鈴木" };

int index = Array.IndexOf(names, "高橋");

Console.WriteLine(index); // -1

4-3. 数値配列から要素の位置を取得する例

数値配列でも同じように使えます。

C#
int[] numbers = { 10, 20, 30, 40 };

int index = Array.IndexOf(numbers, 30);

Console.WriteLine(index); // 2

同じ値が複数ある場合は、最初に見つかった位置だけが返ります。

C#
int[] numbers = { 10, 20, 10, 30 };

int index = Array.IndexOf(numbers, 10);

Console.WriteLine(index); // 0

4-4. 配列の途中から検索する方法

配列でも、検索開始位置を指定できます。

C#
int[] numbers = { 10, 20, 10, 30 };

int index = Array.IndexOf(numbers, 10, 1);

Console.WriteLine(index); // 2

この例では、インデックス1から検索を開始しているため、インデックス010は無視されます。

検索範囲を指定することもできます。

C#
int[] numbers = { 10, 20, 10, 30, 10 };

int index = Array.IndexOf(numbers, 10, 1, 3);

Console.WriteLine(index); // 2

インデックス1から3個分、つまり20, 10, 30の範囲で検索しています。

4-5. 多次元配列ではそのまま使えない点に注意

Array.IndexOfは、基本的に1次元配列で使うものです。

次のような多次元配列では、そのまま期待通りに検索できません。

C#
int[,] matrix =
{
{ 1, 2 },
{ 3, 4 }
};

// Array.IndexOf(matrix, 3) のようには使わない

多次元配列を検索したい場合は、ループを使って行と列を調べます。

C#
int[,] matrix =
{
{ 1, 2 },
{ 3, 4 }
};

for (int row = 0; row < matrix.GetLength(0); row++)
{
for (int col = 0; col < matrix.GetLength(1); col++)
{
if (matrix[row, col] == 3)
{
Console.WriteLine($"見つかりました: row={row}, col={col}");
}
}
}

多次元配列では、単純なインデックス1つではなく、行と列の位置を考える必要があります。

5. IndexOfの戻り値-1の意味と安全な判定方法

IndexOfを使ううえで最も重要なのが、戻り値-1の扱いです。

5-1. -1が返るのは「見つからなかった」という意味

IndexOfで検索対象が見つからない場合、戻り値は-1になります。

C#
string text = "Hello";

int index = text.IndexOf("x");

Console.WriteLine(index); // -1

-1は有効なインデックスではありません。

C#のインデックスは0以上なので、-1が返ったら「対象が存在しない」と判断します。

5-2. if文でIndexOfの結果を判定する基本パターン

IndexOfの結果を判定するときは、次のように書くのが基本です。

C#
string text = "Hello C#";

int index = text.IndexOf("C#");

if (index != -1)
{
Console.WriteLine("見つかりました");
}
else
{
Console.WriteLine("見つかりませんでした");
}

また、0以上かどうかで判定する書き方もよく使われます。

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

index >= 0は、「有効なインデックスである」という意味になるため分かりやすいです。

5-3. 「0」と「-1」を混同しないための注意点

IndexOfでは、0は「見つからなかった」ではありません。

0は「先頭で見つかった」という意味です。

C#
string text = "apple";

int index = text.IndexOf("a");

Console.WriteLine(index); // 0

次のような判定は間違いです。

C#
string text = "apple";

if (text.IndexOf("a") > 0)
{
Console.WriteLine("見つかりました");
}

このコードでは、aがインデックス0で見つかっているにもかかわらず、条件がfalseになります。

正しくは次のように書きます。

C#
if (text.IndexOf("a") >= 0)
{
Console.WriteLine("見つかりました");
}

または次のように書きます。

C#
if (text.IndexOf("a") != -1)
{
Console.WriteLine("見つかりました");
}

5-4. IndexOfの結果を使って文字列を切り出す例

IndexOfで取得した位置は、Substringと組み合わせると便利です。

たとえば、:より前の文字列を取得してみます。

C#
string text = "Name:Tanaka";

int index = text.IndexOf(":");

if (index != -1)
{
string key = text.Substring(0, index);
Console.WriteLine(key); // Name
}

Substring(0, index)は、先頭からindex文字分を切り出します。

:より後ろの文字列を取得する場合は、次のように書きます。

C#
string text = "Name:Tanaka";

int index = text.IndexOf(":");

if (index != -1)
{
string value = text.Substring(index + 1);
Console.WriteLine(value); // Tanaka
}

index + 1にすることで、区切り文字である:の次の位置から切り出せます。

5-5. -1のままSubstringやRemoveに渡すとエラーになる理由

IndexOfの戻り値が-1のままSubstringRemoveに渡されると、範囲外の位置を指定したことになり、例外が発生します。

C#
string text = "Hello";

int index = text.IndexOf("@");

string result = text.Substring(0, index); // エラー

この場合、index-1です。

Substring(0, -1)のような指定になってしまうため、不正な範囲として扱われます。

安全に書くには、必ず-1ではないことを確認します。

C#
string text = "Hello";

int index = text.IndexOf("@");

if (index != -1)
{
string result = text.Substring(0, index);
Console.WriteLine(result);
}
else
{
Console.WriteLine("@は見つかりませんでした");
}

IndexOfの結果を加工処理に使うときは、必ず見つかったかどうかを確認しましょう。

6. IndexOfとContainsの違い

IndexOfと似たメソッドにContainsがあります。

どちらも「含まれているか」を調べる場面で使えますが、目的が少し異なります。

6-1. IndexOfは「位置」を知りたいときに使う

IndexOfは、検索した文字や要素がどこにあるかを知りたいときに使います。

C#
string text = "Hello C#";

int index = text.IndexOf("C#");

Console.WriteLine(index); // 6

戻り値はint型です。

見つかった場合は位置、見つからない場合は-1が返ります。

6-2. Containsは「含まれているか」だけを知りたいときに使う

Containsは、対象が含まれているかどうかだけを調べるメソッドです。

C#
string text = "Hello C#";

bool result = text.Contains("C#");

Console.WriteLine(result); // True

戻り値はbool型です。

含まれていればtrue、含まれていなければfalseになります。

6-3. 戻り値の違い:intとbool

IndexOfContainsの大きな違いは戻り値です。

C#
string text = "Hello C#";

int index = text.IndexOf("C#");
bool contains = text.Contains("C#");

Console.WriteLine(index); // 6
Console.WriteLine(contains); // True

IndexOfは位置を返します。

Containsは真偽値を返します。

位置を使う必要がない場合は、Containsのほうが読みやすいです。

6-4. 条件分岐だけならContainsのほうが読みやすい

単純に「含まれていたら処理する」という条件分岐だけなら、Containsを使うと意図が分かりやすくなります。

C#
string text = "error: file not found";

if (text.Contains("error"))
{
Console.WriteLine("エラーが含まれています");
}

同じ処理はIndexOfでも書けます。

C#
if (text.IndexOf("error") != -1)
{
Console.WriteLine("エラーが含まれています");
}

ただし、位置を使わないならContainsのほうが自然です。

6-5. 位置を使って加工・削除・抽出するならIndexOfを使う

文字列の一部を切り出したり、Listの要素を更新したりする場合はIndexOfが向いています。

C#
string text = "id=12345";

int index = text.IndexOf("=");

if (index != -1)
{
string value = text.Substring(index + 1);
Console.WriteLine(value); // 12345
}

このように、見つかった位置を使って後続の処理を行う場合はIndexOfを使いましょう。

判断の目安は次のとおりです。

C#
// 含まれているかだけ知りたい → Contains
// 位置を知りたい、位置を使って加工したい → IndexOf

7. IndexOfの実践的な使い方

ここからは、IndexOfを実際のプログラムでどのように使うかを見ていきます。

7-1. 特定の文字より前の文字列を取得する

特定の文字より前を取り出すには、IndexOfで位置を取得し、Substringで切り出します。

C#
string text = "apple,banana";

int index = text.IndexOf(",");

if (index != -1)
{
string before = text.Substring(0, index);
Console.WriteLine(before); // apple
}

CSVのように区切り文字がある文字列を扱うときに使えます。

7-2. 特定の文字より後ろの文字列を取得する

特定の文字より後ろを取り出す場合は、index + 1から切り出します。

C#
string text = "apple,banana";

int index = text.IndexOf(",");

if (index != -1)
{
string after = text.Substring(index + 1);
Console.WriteLine(after); // banana
}

区切り文字自体を含めたくないため、index + 1を指定しています。

複数文字の区切り文字を使う場合は、区切り文字の長さを足します。

C#
string text = "name=>Tanaka";

string separator = "=>";
int index = text.IndexOf(separator);

if (index != -1)
{
string after = text.Substring(index + separator.Length);
Console.WriteLine(after); // Tanaka
}

7-3. メールアドレスの@位置を調べる

メールアドレスの@の位置を調べる例です。

C#
string email = "user@example.com";

int index = email.IndexOf("@");

if (index != -1)
{
Console.WriteLine("@の位置: " + index);
}
else
{
Console.WriteLine("メールアドレスに@が含まれていません");
}

@より前をユーザー名、後ろをドメインとして取り出すこともできます。

C#
string email = "user@example.com";

int index = email.IndexOf("@");

if (index != -1)
{
string userName = email.Substring(0, index);
string domain = email.Substring(index + 1);

Console.WriteLine(userName); // user
Console.WriteLine(domain); // example.com
}

ただし、実際のメールアドレス検証はもっと複雑です。

簡単な分割であればIndexOfで対応できますが、厳密な検証が必要な場合は専用の処理を検討しましょう。

7-4. URLやファイルパスの一部を取り出す

URLから特定の部分を取り出すときにもIndexOfは使えます。

C#
string url = "https://example.com/products";

int index = url.IndexOf("://");

if (index != -1)
{
string protocol = url.Substring(0, index);
Console.WriteLine(protocol); // https
}

ファイルパスからフォルダやファイル名を扱うときにも使えます。

C#
string path = @"C:\work\sample.txt";

int index = path.IndexOf("sample");

if (index != -1)
{
Console.WriteLine("sampleの位置: " + index);
}

ただし、ファイルパスを本格的に扱う場合は、System.IO.Pathクラスを使うほうが安全です。

C#
string path = @"C:\work\sample.txt";

string fileName = Path.GetFileName(path);

Console.WriteLine(fileName); // sample.txt

IndexOfは簡単な文字列検索に便利ですが、URLやパスの解析には専用クラスのほうが適している場合があります。

7-5. Listや配列から見つけた要素を更新・削除する

Listで見つかった要素を更新する例です。

C#
List<string> fruits = new List<string>
{
"apple",
"banana",
"orange"
};

int index = fruits.IndexOf("banana");

if (index != -1)
{
fruits[index] = "grape";
}

Console.WriteLine(string.Join(", ", fruits)); // apple, grape, orange

削除する場合も、IndexOfで位置を調べてからRemoveAtを使えます。

C#
List<string> fruits = new List<string>
{
"apple",
"banana",
"orange"
};

int index = fruits.IndexOf("banana");

if (index != -1)
{
fruits.RemoveAt(index);
}

Console.WriteLine(string.Join(", ", fruits)); // apple, orange

配列の場合は要素数を変更できないため、値を更新することはできますが、削除には向いていません。

C#
string[] fruits = { "apple", "banana", "orange" };

int index = Array.IndexOf(fruits, "banana");

if (index != -1)
{
fruits[index] = "grape";
}

Console.WriteLine(string.Join(", ", fruits)); // apple, grape, orange

配列から要素を削除したい場合は、Listに変換して処理する方法があります。

C#
string[] fruits = { "apple", "banana", "orange" };

List<string> list = fruits.ToList();

int index = list.IndexOf("banana");

if (index != -1)
{
list.RemoveAt(index);
}

fruits = list.ToArray();

Console.WriteLine(string.Join(", ", fruits)); // apple, orange

8. IndexOfでよくあるエラーと解決方法

IndexOfは便利ですが、使い方を間違えるとバグや例外の原因になります。

ここでは、初心者がよくつまずくポイントを解説します。

8-1. 戻り値-1を考慮せず例外が発生する

最も多いミスは、IndexOfの結果が-1になる可能性を考えずに使ってしまうことです。

C#
string text = "Hello";

int index = text.IndexOf("@");

string result = text.Substring(0, index); // エラー

この場合、@が見つからないためindex-1です。

必ず確認してから使いましょう。

C#
string text = "Hello";

int index = text.IndexOf("@");

if (index != -1)
{
string result = text.Substring(0, index);
Console.WriteLine(result);
}
else
{
Console.WriteLine("@は見つかりませんでした");
}

8-2. インデックスが0始まりであることを忘れる

C#のインデックスは0から始まります。

C#
string text = "abc";

Console.WriteLine(text.IndexOf("a")); // 0
Console.WriteLine(text.IndexOf("b")); // 1
Console.WriteLine(text.IndexOf("c")); // 2

先頭で見つかった場合の戻り値は0です。

そのため、次のような条件は避けましょう。

C#
if (text.IndexOf("a") > 0)
{
Console.WriteLine("見つかりました");
}

正しくは次のように書きます。

C#
if (text.IndexOf("a") >= 0)
{
Console.WriteLine("見つかりました");
}

8-3. 大文字・小文字の違いで検索に失敗する

IndexOfは基本的に大文字・小文字を区別します。

C#
string text = "Sample Text";

int index = text.IndexOf("sample");

Console.WriteLine(index); // -1

大文字・小文字を無視したい場合は、StringComparison.OrdinalIgnoreCaseを使います。

C#
string text = "Sample Text";

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

Console.WriteLine(index); // 0

ファイル拡張子やコマンド文字列などを検索するときに便利です。

8-4. 全角・半角や空白の違いで見つからない

見た目が似ていても、文字が異なるとIndexOfでは一致しません。

C#
string text = "商品コード:ABC123";

Console.WriteLine(text.IndexOf(":")); // -1
Console.WriteLine(text.IndexOf(":")); // 4

1つ目は半角コロン、2つ目は全角コロンです。

空白も同様です。

C#
string text = "Hello World"; // HelloとWorldの間は全角スペース

Console.WriteLine(text.IndexOf(" ")); // -1
Console.WriteLine(text.IndexOf(" ")); // 5

データ入力や外部ファイルの読み込みでは、全角・半角、余分な空白、改行などが原因で検索に失敗することがあります。

必要に応じてTrimReplaceを使って整えるとよいでしょう。

C#
string text = " Hello ";

text = text.Trim();

Console.WriteLine(text.IndexOf("Hello")); // 0

8-5. Listと配列でIndexOfの書き方を間違える

Listと配列では、IndexOfの書き方が違います。

Listの場合は、Listのインスタンスに対して呼び出します。

C#
List<string> list = new List<string> { "A", "B", "C" };

int index = list.IndexOf("B");

配列の場合は、Array.IndexOfを使います。

C#
string[] array = { "A", "B", "C" };

int index = Array.IndexOf(array, "B");

初心者のうちは、次のように覚えると分かりやすいです。

C#
// string  → text.IndexOf(...)
// List → list.IndexOf(...)
// 配列 → Array.IndexOf(array, ...)

9. IndexOfと関連メソッドの使い分け

C#には、IndexOf以外にも検索に使えるメソッドがあります。

目的に合わせて使い分けると、コードが読みやすくなります。

9-1. LastIndexOf:最後に出現する位置を探す

LastIndexOfは、最後に出現する位置を探すメソッドです。

C#
string text = "apple apple";

int index = text.LastIndexOf("apple");

Console.WriteLine(index); // 6

IndexOfは前から検索しますが、LastIndexOfは後ろから検索します。

ファイルパスの最後の区切り文字を探すような場面で使えます。

C#
string path = @"C:\work\sample.txt";

int index = path.LastIndexOf("\\");

if (index != -1)
{
string fileName = path.Substring(index + 1);
Console.WriteLine(fileName); // sample.txt
}

ただし、ファイル名の取得だけならPath.GetFileNameのほうが適しています。

9-2. StartsWith:先頭一致を調べる

StartsWithは、文字列が指定した文字列で始まるかどうかを調べます。

C#
string text = "https://example.com";

bool result = text.StartsWith("https");

Console.WriteLine(result); // True

先頭にあるかどうかだけを知りたい場合は、IndexOfよりStartsWithのほうが分かりやすいです。

C#
string text = "https://example.com";

if (text.StartsWith("https"))
{
Console.WriteLine("HTTPSのURLです");
}

9-3. EndsWith:末尾一致を調べる

EndsWithは、文字列が指定した文字列で終わるかどうかを調べます。

C#
string fileName = "sample.pdf";

bool result = fileName.EndsWith(".pdf");

Console.WriteLine(result); // True

ファイル拡張子の確認などによく使います。

大文字・小文字を区別したくない場合は、比較方法を指定します。

C#
string fileName = "sample.PDF";

bool result = fileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

9-4. FindIndex:条件に一致するList要素を探す

FindIndexは、Listの中から条件に一致する要素の位置を探すメソッドです。

C#
List<int> numbers = new List<int> { 10, 20, 30, 40 };

int index = numbers.FindIndex(n => n >= 30);

Console.WriteLine(index); // 2

IndexOfは「指定した値そのもの」を探すのに向いています。

一方、FindIndexは「条件に合う要素」を探すのに向いています。

自作クラスの検索でも便利です。

C#
class User
{
public string Name { get; set; }
public int Age { get; set; }
}

List<User> users = new List<User>
{
new User { Name = "田中", Age = 20 },
new User { Name = "佐藤", Age = 30 }
};

int index = users.FindIndex(user => user.Age >= 30);

Console.WriteLine(index); // 1

オブジェクトのプロパティを条件にして探したい場合は、IndexOfよりFindIndexを使うとよいでしょう。

9-5. LINQのAny・FirstOrDefaultとの違い

LINQのAnyFirstOrDefaultも検索処理でよく使われます。

Anyは、条件に一致する要素が存在するかどうかを調べます。

C#
List<int> numbers = new List<int> { 10, 20, 30 };

bool exists = numbers.Any(n => n >= 20);

Console.WriteLine(exists); // True

FirstOrDefaultは、条件に一致する最初の要素を取得します。

C#
List<int> numbers = new List<int> { 10, 20, 30 };

int value = numbers.FirstOrDefault(n => n >= 20);

Console.WriteLine(value); // 20

ただし、AnyFirstOrDefaultは、基本的に「位置」ではなく「存在するか」や「要素そのもの」を扱います。

位置が必要な場合は、IndexOfFindIndexを使います。

C#
List<int> numbers = new List<int> { 10, 20, 30 };

int index = numbers.FindIndex(n => n >= 20);

Console.WriteLine(index); // 1

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

C#
// 値の位置を知りたい        → IndexOf
// 最後の位置を知りたい → LastIndexOf
// 先頭一致を調べたい → StartsWith
// 末尾一致を調べたい → EndsWith
// 条件に合う位置を知りたい → FindIndex
// 存在するかだけ知りたい → Contains / Any
// 要素そのものを取得したい → FirstOrDefault

まとめ

C#のIndexOfは、文字列・List・配列の中から指定した文字や要素を検索し、その位置を取得するためのメソッドです。

文字列では、次のように使います。

C#
string text = "Hello C#";

int index = text.IndexOf("C#");

Console.WriteLine(index); // 6

Listでは、次のように使います。

C#
List<string> list = new List<string> { "A", "B", "C" };

int index = list.IndexOf("B");

Console.WriteLine(index); // 1

配列では、Array.IndexOfを使います。

C#
string[] array = { "A", "B", "C" };

int index = Array.IndexOf(array, "B");

Console.WriteLine(index); // 1

IndexOfで特に重要なのは、見つからなかった場合に-1が返ることです。

C#
string text = "Hello";

int index = text.IndexOf("x");

Console.WriteLine(index); // -1

-1を確認せずにSubstringRemoveなどへ渡すとエラーになるため、必ず判定してから使いましょう。

C#
if (index != -1)
{
Console.WriteLine("見つかりました");
}

また、単純に「含まれているか」だけを知りたい場合はContains、位置を使って加工や更新をしたい場合はIndexOfを使うと分かりやすくなります。

C#
// 含まれているかだけ知りたい
text.Contains("C#");

// 位置を知りたい
text.IndexOf("C#");

IndexOfはC#の文字列操作やコレクション操作で頻繁に使う基本メソッドです。

戻り値の意味、0始まりのインデックス、-1の扱いを理解しておけば、文字列の切り出し、検索、Listや配列の更新処理などで安全に活用できます。