C# Substringの使い方を初心者向けに解説|開始位置・文字数指定・例外対策までわかるサンプル集

はじめに

C#で文字列の一部だけを取り出したいときによく使うのが、Substringメソッドです。

たとえば、次のような処理をしたい場面で役立ちます。

C#
string text = "Hello World";
string result = text.Substring(6);

Console.WriteLine(result);

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

C#
World

このように、Substringを使うと文字列の途中から一部を簡単に切り出せます。

ただし、C#のSubstringは開始位置や文字数の指定を間違えると、ArgumentOutOfRangeExceptionという例外が発生します。初心者のうちは、「なぜエラーになるのか」「開始位置は何番から数えるのか」「文字数の指定はどう考えるのか」でつまずきやすいです。

この記事では、C#のSubstringの基本的な使い方から、開始位置・文字数の指定方法、よくある例外、安全な書き方、実用的なサンプルまで初心者向けにわかりやすく解説します。

1. C#のSubstringとは?文字列の一部を取り出す基本メソッド

C#のSubstringは、文字列から一部分を取り出すためのメソッドです。

Substringは英語で「部分文字列」という意味があり、C#ではstring型の文字列に対して使用できます。

C#
string text = "CSharp";
string part = text.Substring(1, 3);

Console.WriteLine(part);

実行結果は次のとおりです。

C#
Sha

この例では、文字列"CSharp"の1番目から3文字分を取り出しています。

1-1. Substringでできること

Substringを使うと、文字列の中から指定した範囲だけを取り出せます。

代表的な使い方は次の2つです。

C#
Substring(開始位置)

指定した開始位置から最後まで取り出します。

C#
Substring(開始位置, 文字数)

指定した開始位置から、指定した文字数分だけ取り出します。

たとえば、商品コード、郵便番号、ファイル名、日付文字列など、決まった位置に意味のある文字が入っているデータを扱うときに便利です。

C#
string code = "ABC-12345";
string prefix = code.Substring(0, 3);

Console.WriteLine(prefix);

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

C#
ABC

1-2. Substringが返す値と元の文字列が変わらない理由

Substringは、取り出した文字列を新しい文字列として返します。

元の文字列そのものは変更されません。

C#
string text = "Hello World";
string part = text.Substring(0, 5);

Console.WriteLine(text);
Console.WriteLine(part);

実行結果は次のとおりです。

C#
Hello World
Hello

textには元の"Hello World"がそのまま残り、part"Hello"が入ります。

C#のstringは変更できない型です。この性質を「不変」といいます。文字列操作を行っても、元の文字列が直接書き換わるのではなく、新しい文字列が作られると考えると理解しやすいです。

1-3. Substringを使う場面の具体例

Substringは、次のような場面でよく使われます。

C#
string postalCode = "123-4567";
string firstPart = postalCode.Substring(0, 3);

Console.WriteLine(firstPart);

実行結果は次のとおりです。

C#
123

郵便番号の前半だけを取り出す例です。

C#
string date = "20260415";
string year = date.Substring(0, 4);
string month = date.Substring(4, 2);
string day = date.Substring(6, 2);

Console.WriteLine(year);
Console.WriteLine(month);
Console.WriteLine(day);

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

C#
2026
04
15

このように、固定された形式の文字列から必要な部分を取り出すときにSubstringは非常に便利です。

2. C# Substringの基本構文

C#のSubstringには、主に2種類の使い方があります。

C#
文字列.Substring(int startIndex)
文字列.Substring(int startIndex, int length)

それぞれの違いを理解しておくと、文字列の切り出しで迷いにくくなります。

2-1. Substring(int startIndex)の使い方

Substring(int startIndex)は、指定した開始位置から文字列の最後までを取り出します。

C#
string text = "Programming";
string result = text.Substring(3);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
gramming

"Programming"の文字位置は次のように数えます。

C#
P r o g r a m m i n g
0 1 2 3 4 5 6 7 8 9 10

startIndex3を指定しているため、3番目のgから最後までが取り出されます。

2-2. Substring(int startIndex, int length)の使い方

Substring(int startIndex, int length)は、指定した開始位置から指定した文字数分だけ取り出します。

C#
string text = "Programming";
string result = text.Substring(0, 7);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Program

この例では、0番目から7文字分を取り出しています。

lengthは「終了位置」ではなく「取り出す文字数」です。この点は非常に重要です。

2-3. startIndexは0から数える点に注意

C#の文字列の位置は、1ではなく0から数えます。

C#
string text = "ABCDE";

それぞれの文字の位置は次のようになります。

C#
A B C D E
0 1 2 3 4

たとえば、Cから取り出したい場合は、startIndex2を指定します。

C#
string text = "ABCDE";
string result = text.Substring(2);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
CDE

初心者がよく間違えるポイントは、「3文字目だから3を指定する」と考えてしまうことです。

C#では3文字目の位置は2です。

2-4. lengthは「終了位置」ではなく「文字数」を指定する

Substring(startIndex, length)の第2引数は、終了位置ではありません。

次のコードを見てみましょう。

C#
string text = "ABCDE";
string result = text.Substring(1, 3);

Console.WriteLine(result);

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

C#
BCD

startIndex1なので、Bから取り出します。

length3なので、BCDの3文字を取得します。

つまり、Substring(1, 3)は「1番目から3番目まで」ではなく、「1番目から3文字分」という意味です。

3. 開始位置を指定して文字列を取り出すサンプル

ここでは、Substring(startIndex)を使って、指定した位置から最後まで文字列を取り出すサンプルを紹介します。

3-1. 指定位置から最後まで取り出す

C#
string text = "Hello CSharp";
string result = text.Substring(6);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
CSharp

"Hello CSharp"では、Cの位置が6です。

C#
H e l l o   C S h a r p
0 1 2 3 4 5 6 7 8 9 10 11

そのため、Substring(6)"CSharp"を取り出せます。

3-2. 先頭以外から文字列を取り出す

先頭の数文字を除外して、後ろだけを取得したい場合にもSubstringは便利です。

C#
string id = "ID-000123";
string number = id.Substring(3);

Console.WriteLine(number);

実行結果は次のとおりです。

C#
000123

この例では、先頭の"ID-"を除いて、番号部分だけを取り出しています。

3-3. 空白や記号を含む文字列での使い方

Substringは、空白や記号も1文字として扱います。

C#
string text = "Name: Tanaka";
string name = text.Substring(6);

Console.WriteLine(name);

実行結果は次のとおりです。

C#
Tanaka

この文字列では、Name:の後ろに空白があります。

C#
N a m e :   T a n a k a
0 1 2 3 4 5 6 7 8 9 10 11

空白も1文字として数えるため、Tの位置は6になります。

記号を含む場合も同じです。

C#
string text = "user@example.com";
string domain = text.Substring(5);

Console.WriteLine(domain);

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

C#
example.com

4. 開始位置と文字数を指定して文字列を取り出すサンプル

ここでは、Substring(startIndex, length)を使って、開始位置と文字数を指定するサンプルを紹介します。

4-1. 先頭から指定文字数だけ取り出す

先頭から数文字だけ取り出したい場合は、startIndex0を指定します。

C#
string text = "CSharp";
string result = text.Substring(0, 1);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
C

先頭3文字を取り出す場合は次のように書きます。

C#
string text = "CSharp";
string result = text.Substring(0, 3);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
CSh

4-2. 中間の文字列だけ取り出す

文字列の中間部分だけを取り出すこともできます。

C#
string text = "ABC-123-XYZ";
string number = text.Substring(4, 3);

Console.WriteLine(number);

実行結果は次のとおりです。

C#
123

文字位置を確認すると、次のようになります。

C#
A B C - 1 2 3 - X Y Z
0 1 2 3 4 5 6 7 8 9 10

1の位置が4で、そこから3文字分を取得しているため、"123"になります。

4-3. 末尾の数文字を取り出す

末尾の数文字を取り出すには、文字列の長さを表すLengthを使います。

C#
string text = "Sample123";
string result = text.Substring(text.Length - 3, 3);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
123

text.Lengthは文字列の長さです。

"Sample123"は9文字なので、text.Length - 36になります。

6番目から3文字分を取り出すため、末尾の"123"を取得できます。

文字数だけを指定して最後まで取り出す場合は、第2引数を省略できます。

C#
string text = "Sample123";
string result = text.Substring(text.Length - 3);

Console.WriteLine(result);

実行結果は同じです。

C#
123

4-4. ファイル名・日付・コード値を切り出す実践例

実際の開発では、決まった形式の文字列から必要な部分を取り出す場面が多くあります。

ファイル名から日付部分を取り出す例です。

C#
string fileName = "log_20260415.txt";
string date = fileName.Substring(4, 8);

Console.WriteLine(date);

実行結果は次のとおりです。

C#
20260415

日付文字列から年、月、日を分ける例です。

C#
string date = "20260415";

string year = date.Substring(0, 4);
string month = date.Substring(4, 2);
string day = date.Substring(6, 2);

Console.WriteLine(year);
Console.WriteLine(month);
Console.WriteLine(day);

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

C#
2026
04
15

商品コードから分類コードと番号を取り出す例です。

C#
string productCode = "BK20260001";

string category = productCode.Substring(0, 2);
string year = productCode.Substring(2, 4);
string number = productCode.Substring(6, 4);

Console.WriteLine(category);
Console.WriteLine(year);
Console.WriteLine(number);

実行結果は次のとおりです。

C#
BK
2026
0001

このように、固定長の文字列を扱う場合、Substringはシンプルで使いやすい方法です。

5. Substringでよく起きる例外と原因

C#のSubstringで最もよく発生するエラーが、ArgumentOutOfRangeExceptionです。

これは、指定した開始位置や文字数が文字列の範囲外になっているときに発生します。

5-1. ArgumentOutOfRangeExceptionが発生する条件

ArgumentOutOfRangeExceptionは、主に次のような場合に発生します。

C#
string text = "ABC";
string result = text.Substring(5);

このコードでは、文字列の長さが3しかないのに、開始位置に5を指定しています。

そのため、範囲外となり例外が発生します。

また、次のようなコードもエラーになります。

C#
string text = "ABC";
string result = text.Substring(1, 5);

開始位置の1は問題ありませんが、そこから5文字分を取り出そうとすると、文字列の長さを超えてしまいます。

5-2. startIndexが文字列の長さを超えるケース

startIndexは、0以上かつ文字列の長さ以下である必要があります。

C#
string text = "Hello";

Console.WriteLine(text.Length);

実行結果は次のとおりです。

C#
5

この文字列の有効な文字位置は0から4です。

C#
H e l l o
0 1 2 3 4

そのため、次のコードはエラーになります。

C#
string text = "Hello";
string result = text.Substring(6);

startIndexが文字列の長さを超えているためです。

ただし、startIndexに文字列の長さと同じ値を指定した場合は、空文字が返ります。

C#
string text = "Hello";
string result = text.Substring(5);

Console.WriteLine($"[{result}]");

実行結果は次のとおりです。

C#
[]

Substring(5)は、文字列の末尾のさらに後ろから最後までを取り出すため、結果は空文字になります。

5-3. startIndex + lengthが文字列の長さを超えるケース

Substring(startIndex, length)では、startIndex + lengthが文字列の長さを超えるとエラーになります。

C#
string text = "Hello";
string result = text.Substring(2, 10);

startIndex2なので、lから取り出そうとしています。

しかし、そこから10文字分は存在しないため、例外が発生します。

安全に使うには、次の条件を意識します。

C#
startIndex >= 0
length >= 0
startIndex + length <= text.Length

この条件を満たしていれば、Substringで範囲外エラーを避けやすくなります。

5-4. 負の値を指定した場合のエラー

startIndexlengthに負の値を指定してもエラーになります。

C#
string text = "Hello";
string result = text.Substring(-1);

また、次のようにlengthが負の値になる場合もエラーです。

C#
string text = "Hello";
string result = text.Substring(1, -2);

ユーザー入力や計算結果を使ってSubstringする場合は、値が負になっていないか確認することが重要です。

6. 例外を防ぐ安全なSubstringの書き方

Substringは便利ですが、範囲外の値を指定すると例外が発生します。

実際の開発では、事前に文字列の長さやnullを確認してから使うのが安全です。

6-1. Lengthで文字列の長さを確認する

Lengthを使うと、文字列の長さを確認できます。

C#
string text = "Hello";

if (text.Length >= 3)
{
string result = text.Substring(0, 3);
Console.WriteLine(result);
}

実行結果は次のとおりです。

C#
Hel

このように、必要な文字数があるかを確認してからSubstringを使うと、エラーを防げます。

6-2. if文で範囲外アクセスを防ぐ

開始位置と文字数を変数で指定する場合は、範囲チェックを行いましょう。

C#
string text = "Hello";
int startIndex = 1;
int length = 3;

if (startIndex >= 0 &&
length >= 0 &&
startIndex + length <= text.Length)
{
string result = text.Substring(startIndex, length);
Console.WriteLine(result);
}
else
{
Console.WriteLine("指定範囲が文字列の長さを超えています。");
}

実行結果は次のとおりです。

C#
ell

startIndex + length <= text.Lengthを確認するのがポイントです。

6-3. nullや空文字を事前にチェックする

文字列がnullの場合、Substringを呼び出すとNullReferenceExceptionが発生します。

C#
string text = null;
string result = text.Substring(0, 1);

このようなエラーを防ぐには、string.IsNullOrEmptyを使います。

C#
string text = null;

if (!string.IsNullOrEmpty(text))
{
string result = text.Substring(0, 1);
Console.WriteLine(result);
}
else
{
Console.WriteLine("文字列がnullまたは空です。");
}

空白だけの文字列も除外したい場合は、string.IsNullOrWhiteSpaceを使います。

C#
string text = "   ";

if (!string.IsNullOrWhiteSpace(text))
{
string result = text.Substring(0, 1);
Console.WriteLine(result);
}
else
{
Console.WriteLine("文字列がnull、空、または空白のみです。");
}

6-4. 安全に切り出すヘルパーメソッドを作る

Substringを何度も使う場合は、安全に切り出すためのヘルパーメソッドを作っておくと便利です。

C#
static string SafeSubstring(string text, int startIndex, int length)
{
if (string.IsNullOrEmpty(text))
{
return string.Empty;
}

if (startIndex < 0 || length < 0)
{
return string.Empty;
}

if (startIndex >= text.Length)
{
return string.Empty;
}

if (startIndex + length > text.Length)
{
length = text.Length - startIndex;
}

return text.Substring(startIndex, length);
}

使用例は次のとおりです。

C#
string text = "Hello";
string result = SafeSubstring(text, 2, 10);

Console.WriteLine(result);

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

C#
llo

このヘルパーメソッドでは、指定文字数が文字列の長さを超える場合でも、取得できる範囲だけを返すようにしています。

7. Substringを使った実用サンプル集

ここでは、実際の開発で使いやすいSubstringのサンプルを紹介します。

7-1. 郵便番号や電話番号の一部を取り出す

郵便番号の前半と後半を分ける例です。

C#
string postalCode = "123-4567";

string first = postalCode.Substring(0, 3);
string second = postalCode.Substring(4, 4);

Console.WriteLine(first);
Console.WriteLine(second);

実行結果は次のとおりです。

C#
123
4567

電話番号の一部を取り出す例です。

C#
string phone = "090-1234-5678";

string area = phone.Substring(0, 3);
string middle = phone.Substring(4, 4);
string last = phone.Substring(9, 4);

Console.WriteLine(area);
Console.WriteLine(middle);
Console.WriteLine(last);

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

C#
090
1234
5678

ただし、電話番号は形式が複数あるため、実務ではSplitや正規表現を使ったほうがよい場合もあります。

7-2. 拡張子を除いたファイル名を取得する

ファイル名から拡張子を除きたい場合は、LastIndexOfSubstringを組み合わせます。

C#
string fileName = "report.xlsx";
int dotIndex = fileName.LastIndexOf('.');

string nameWithoutExtension = fileName.Substring(0, dotIndex);

Console.WriteLine(nameWithoutExtension);

実行結果は次のとおりです。

C#
report

.の位置を取得し、その手前までをSubstringで取り出しています。

安全に書くなら、.が存在するかを確認します。

C#
string fileName = "report.xlsx";
int dotIndex = fileName.LastIndexOf('.');

if (dotIndex > 0)
{
string nameWithoutExtension = fileName.Substring(0, dotIndex);
Console.WriteLine(nameWithoutExtension);
}
else
{
Console.WriteLine(fileName);
}

なお、実務でファイルパスを扱う場合は、Path.GetFileNameWithoutExtensionを使う方法もあります。

C#
using System.IO;

string fileName = "report.xlsx";
string result = Path.GetFileNameWithoutExtension(fileName);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
report

7-3. メールアドレスのユーザー名部分を取り出す

メールアドレスの@より前を取得する例です。

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

string userName = email.Substring(0, atIndex);

Console.WriteLine(userName);

実行結果は次のとおりです。

C#
tanaka

安全に書く場合は、@が存在するか確認します。

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

if (atIndex > 0)
{
string userName = email.Substring(0, atIndex);
Console.WriteLine(userName);
}
else
{
Console.WriteLine("メールアドレスの形式が正しくありません。");
}

7-4. 固定長データから項目を切り出す

固定長データでは、項目ごとの桁数が決まっています。

たとえば、次のようなデータがあるとします。

C#
string data = "TANAKA    025TOKYO     ";

この文字列を、名前、年齢、住所に分ける例です。

C#
string data = "TANAKA    025TOKYO     ";

string name = data.Substring(0, 10).Trim();
string age = data.Substring(10, 3).Trim();
string city = data.Substring(13, 10).Trim();

Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine(city);

実行結果は次のとおりです。

C#
TANAKA
025
TOKYO

固定長データでは、空白が含まれることが多いため、Trimを組み合わせると不要な空白を取り除けます。

7-5. IndexOfと組み合わせて特定文字の前後を取得する

Substringは、IndexOfと組み合わせることで、特定の文字より前や後ろを取得できます。

C#
string text = "category:book";
int colonIndex = text.IndexOf(':');

string key = text.Substring(0, colonIndex);
string value = text.Substring(colonIndex + 1);

Console.WriteLine(key);
Console.WriteLine(value);

実行結果は次のとおりです。

C#
category
book

colonIndex + 1にすることで、:の次の文字から取り出しています。

安全に書く場合は、次のようにします。

C#
string text = "category:book";
int colonIndex = text.IndexOf(':');

if (colonIndex >= 0)
{
string key = text.Substring(0, colonIndex);
string value = text.Substring(colonIndex + 1);

Console.WriteLine(key);
Console.WriteLine(value);
}
else
{
Console.WriteLine("区切り文字が見つかりません。");
}

8. Substringと似た文字列操作メソッドの違い

C#には、Substring以外にも文字列を操作するメソッドがあります。

ここでは、IndexOfSplitReplace、範囲演算子との違いを整理します。

8-1. SubstringとIndexOfの違い

Substringは文字列の一部を取り出すメソッドです。

一方、IndexOfは指定した文字や文字列が何番目にあるかを調べるメソッドです。

C#
string text = "Hello World";

int index = text.IndexOf("World");
string result = text.Substring(index);

Console.WriteLine(index);
Console.WriteLine(result);

実行結果は次のとおりです。

C#
6
World

IndexOfで位置を調べ、Substringでその位置から取り出しています。

つまり、IndexOfは「探す」、Substringは「取り出す」と考えるとわかりやすいです。

8-2. SubstringとSplitの違い

Splitは、区切り文字で文字列を分割するメソッドです。

C#
string text = "apple,banana,orange";
string[] fruits = text.Split(',');

Console.WriteLine(fruits[0]);
Console.WriteLine(fruits[1]);
Console.WriteLine(fruits[2]);

実行結果は次のとおりです。

C#
apple
banana
orange

Substringは位置や文字数を指定して取り出します。

Splitはカンマやスペースなどの区切り文字で分割します。

固定位置で切り出すならSubstring、区切り文字で分けるならSplitが向いています。

8-3. SubstringとReplaceの違い

Replaceは、文字列の一部を別の文字列に置き換えるメソッドです。

C#
string text = "Hello World";
string result = text.Replace("World", "CSharp");

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Hello CSharp

Substringは文字列を取り出すために使います。

Replaceは文字列を置き換えるために使います。

目的が違うため、処理内容に合わせて使い分けましょう。

8-4. C#の範囲演算子[..]との違い

C#では、範囲演算子[..]を使って文字列の一部を取り出すこともできます。

C#
string text = "Hello World";
string result = text[0..5];

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Hello

範囲演算子では、開始位置と終了位置を指定します。

C#
text[0..5]

これは、0番目から5番目の手前までを取り出すという意味です。

Substring(0, 5)と同じ結果になりますが、考え方が少し違います。

C#
string text = "Hello World";

string result1 = text.Substring(0, 5);
string result2 = text[0..5];

Console.WriteLine(result1);
Console.WriteLine(result2);

実行結果は次のとおりです。

C#
Hello
Hello

Substringは第2引数に文字数を指定します。

範囲演算子は終了位置を指定します。

初心者のうちは、Substringlengthと範囲演算子の終了位置を混同しないように注意しましょう。

9. C# Substringを使うときの注意点

Substringはシンプルなメソッドですが、日本語や絵文字、大量処理などでは注意が必要です。

9-1. 全角文字・日本語でも1文字として扱われるのか

通常の日本語文字は、Substringで1文字として扱えます。

C#
string text = "こんにちは";
string result = text.Substring(0, 2);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
こん

このように、ひらがな、カタカナ、漢字などは基本的に1文字として扱えます。

C#
string text = "東京都新宿区";
string result = text.Substring(0, 3);

Console.WriteLine(result);

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

C#
東京都

ただし、すべての見た目の文字が必ず安全に1文字として扱えるわけではありません。

9-2. サロゲートペアや絵文字を扱う場合の注意

C#のstringは、内部的にはUTF-16のコード単位で文字列を扱います。

そのため、絵文字や一部の特殊文字は、見た目は1文字でもLengthが2以上になる場合があります。

C#
string text = "😀";

Console.WriteLine(text.Length);

実行結果は次のようになることがあります。

C#
2

このような文字をSubstringで途中から切り出すと、文字が壊れる可能性があります。

C#
string text = "😀ABC";
string result = text.Substring(0, 1);

Console.WriteLine(result);

このコードでは、絵文字の一部だけを切り出してしまう可能性があります。

絵文字や結合文字を正確に扱いたい場合は、単純なSubstringではなく、テキスト要素単位で処理する方法を検討しましょう。

9-3. 大量処理でのパフォーマンスに注意する

Substringは新しい文字列を作成します。

そのため、大量の文字列を何度も切り出す処理では、メモリ使用量やパフォーマンスに影響することがあります。

たとえば、非常に大きな文字列を何万回もSubstringするような処理では注意が必要です。

C#
string text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

for (int i = 0; i < text.Length; i++)
{
string part = text.Substring(i);
Console.WriteLine(part);
}

小規模な処理では問題になりにくいですが、大量データを扱う場合は、必要な部分だけ処理する設計や、Span<char>などの利用を検討することもあります。

初心者の段階では、まずSubstringの基本を正しく理解することが大切です。

9-4. 可読性を上げる変数名とコメントの付け方

Substringは数値だけを見ると、何を切り出しているのかわかりにくくなることがあります。

次のコードは動きますが、意味が少しわかりにくいです。

C#
string result = code.Substring(2, 4);

このような場合は、変数名を使うと読みやすくなります。

C#
int yearStartIndex = 2;
int yearLength = 4;

string year = code.Substring(yearStartIndex, yearLength);

また、固定長データを扱う場合は、コメントを付けると保守しやすくなります。

C#
// 商品コード形式: 種別2桁 + 年4桁 + 連番4桁
string productCode = "BK20260001";

string category = productCode.Substring(0, 2);
string year = productCode.Substring(2, 4);
string number = productCode.Substring(6, 4);

Substringの引数に直接数値を書く場合でも、その数値が何を意味するのかを明確にしておくことが大切です。

10. C# Substringに関するよくある質問

ここでは、C#のSubstringでよくある質問に回答します。

10-1. 最後の1文字だけ取得するには?

最後の1文字を取得するには、Length - 1を開始位置に指定します。

C#
string text = "Hello";
string lastChar = text.Substring(text.Length - 1);

Console.WriteLine(lastChar);

実行結果は次のとおりです。

C#
o

空文字の可能性がある場合は、事前にチェックしましょう。

C#
string text = "Hello";

if (!string.IsNullOrEmpty(text))
{
string lastChar = text.Substring(text.Length - 1);
Console.WriteLine(lastChar);
}

10-2. 先頭のn文字だけ取得するには?

先頭のn文字を取得するには、Substring(0, n)を使います。

C#
string text = "Hello World";
int n = 5;

string result = text.Substring(0, n);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Hello

ただし、文字列の長さがn未満の場合は例外になります。

安全に書くなら、次のようにします。

C#
string text = "Hi";
int n = 5;

string result = text.Length >= n
? text.Substring(0, n)
: text;

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Hi

10-3. 末尾からn文字を削除するには?

末尾からn文字を削除するには、先頭からLength - n文字分を取得します。

C#
string text = "HelloWorld";
int n = 5;

string result = text.Substring(0, text.Length - n);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Hello

安全に書く場合は、nが文字列の長さを超えないか確認します。

C#
string text = "HelloWorld";
int n = 5;

if (n >= 0 && n <= text.Length)
{
string result = text.Substring(0, text.Length - n);
Console.WriteLine(result);
}
else
{
Console.WriteLine("削除する文字数が不正です。");
}

10-4. 指定文字以降を取り出すには?

指定文字以降を取り出すには、IndexOfで位置を調べてからSubstringを使います。

C#
string text = "Name:Tanaka";
int index = text.IndexOf(':');

string result = text.Substring(index + 1);

Console.WriteLine(result);

実行結果は次のとおりです。

C#
Tanaka

指定文字が存在しない場合に備えて、次のように確認すると安全です。

C#
string text = "Name:Tanaka";
int index = text.IndexOf(':');

if (index >= 0)
{
string result = text.Substring(index + 1);
Console.WriteLine(result);
}
else
{
Console.WriteLine("指定文字が見つかりません。");
}

指定文字より前を取り出したい場合は、次のようにします。

C#
string text = "Name:Tanaka";
int index = text.IndexOf(':');

if (index >= 0)
{
string result = text.Substring(0, index);
Console.WriteLine(result);
}

実行結果は次のとおりです。

C#
Name

10-5. Substringでエラーになるときはどこを確認すべき?

Substringでエラーになる場合は、まず次の点を確認しましょう。

C#
string text = "Hello";
int startIndex = 2;
int length = 10;

Console.WriteLine(text.Length);
Console.WriteLine(startIndex);
Console.WriteLine(length);
Console.WriteLine(startIndex + length);

確認するポイントは次のとおりです。

startIndexが0以上か。

lengthが0以上か。

startIndexが文字列の長さを超えていないか。

startIndex + lengthが文字列の長さを超えていないか。

文字列がnullではないか。

安全にチェックする例は次のとおりです。

C#
string text = "Hello";
int startIndex = 2;
int length = 3;

if (!string.IsNullOrEmpty(text) &&
startIndex >= 0 &&
length >= 0 &&
startIndex + length <= text.Length)
{
string result = text.Substring(startIndex, length);
Console.WriteLine(result);
}
else
{
Console.WriteLine("Substringの指定範囲が不正です。");
}

実行結果は次のとおりです。

C#
llo

Substringでエラーが出たときは、ほとんどの場合、開始位置か文字数が範囲外になっています。

まとめ

C#のSubstringは、文字列の一部を取り出すための基本的で便利なメソッドです。

指定した位置から最後まで取り出す場合は、次のように書きます。

C#
string result = text.Substring(startIndex);

開始位置と文字数を指定して取り出す場合は、次のように書きます。

C#
string result = text.Substring(startIndex, length);

startIndexは0から数える点に注意しましょう。

また、lengthは終了位置ではなく、取り出す文字数を指定します。

Substringを使うときに特に重要なのは、範囲外の指定をしないことです。

C#
startIndex >= 0
length >= 0
startIndex + length <= text.Length

この条件を意識すると、ArgumentOutOfRangeExceptionを防ぎやすくなります。

さらに、実務ではnullや空文字のチェックも重要です。

C#
if (!string.IsNullOrEmpty(text))
{
string result = text.Substring(0, 1);
}

郵便番号、電話番号、ファイル名、日付、固定長データなど、Substringはさまざまな場面で活用できます。

一方で、絵文字やサロゲートペア、大量処理では注意が必要です。

まずは、Substring(startIndex)Substring(startIndex, length)の違いをしっかり理解し、LengthIndexOfと組み合わせながら安全に使えるようになりましょう。