C# Enumerable.Rangeの使い方を基礎から解説|連番生成・foreach・実践例でつまずきを解消
はじめに
C#で「1から10までの連番を作りたい」「指定回数だけ処理を繰り返したい」「LINQでインデックスのような数値を扱いたい」と思ったときに便利なのが、Enumerable.Rangeです。
Enumerable.Rangeを使うと、連続した整数の並びを簡潔に生成できます。for文でも同じような処理は書けますが、LINQと組み合わせることで、連番の生成、加工、抽出、集計などを読みやすく書ける場面があります。
この記事では、C#のEnumerable.Rangeの基本構文から、foreachでの使い方、LINQとの組み合わせ、よくあるエラー、実務で使えるサンプルコードまで、初心者にもわかりやすく解説します。
1. C#のEnumerable.Rangeとは?連番を簡単に生成できるメソッド
1-1. Enumerable.Rangeの基本的な役割
Enumerable.Rangeは、指定した開始値から連続する整数を生成するメソッドです。
たとえば、1から5までの数値を作りたい場合は、次のように書けます。
C#var numbers = Enumerable.Range(1, 5);
foreach (var number in numbers)
{
Console.WriteLine(number);
}
実行結果は次のとおりです。
C#1
2
3
4
5
Enumerable.Range(1, 5)は、「1から始まる数値を5個生成する」という意味です。
ここで重要なのは、第2引数は終了値ではなく、生成する個数を表すという点です。
1-2. どんな場面で使うメソッドなのか
Enumerable.Rangeは、主に次のような場面で使います。
連番を作りたいとき、指定回数だけ処理したいとき、配列やリストのインデックスを扱いたいとき、LINQで数値を加工したいとき、テストデータやダミーデータを作りたいときなどに便利です。
たとえば、ページ番号を作る処理は次のように書けます。
C#var pages = Enumerable.Range(1, 10);
foreach (var page in pages)
{
Console.WriteLine($"ページ {page}");
}
このように、連続した整数を使う処理ではEnumerable.Rangeが役立ちます。
1-3. for文で連番を作る方法との違い
for文で1から5まで表示する場合は、次のように書きます。
C#for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
一方、Enumerable.Rangeを使うと次のようになります。
C#foreach (var i in Enumerable.Range(1, 5))
{
Console.WriteLine(i);
}
for文は、繰り返し処理そのものを書くのに向いています。Enumerable.Rangeは、連番データを作って、それをLINQやforeachで処理したい場合に向いています。
つまり、単純に回数を制御したいならfor文、連番をデータとして扱いたいならEnumerable.Rangeが便利です。
1-4. Enumerable.Rangeを使うメリット
Enumerable.Rangeを使うメリットは、連番生成の意図がわかりやすいことです。
C#var numbers = Enumerable.Range(1, 10);
この1行を見るだけで、「1から始まる10個の連番を作っている」と判断できます。
また、LINQのSelect、Where、Sumなどと組み合わせやすい点も大きな特徴です。
C#var squares = Enumerable.Range(1, 5)
.Select(x => x * x);
このコードでは、1から5までの数値を作り、それぞれを2乗しています。
実行結果は次のようになります。
C#1
4
9
16
25
2. Enumerable.Rangeの基本構文と引数の意味
2-1. Enumerable.Range(start, count)の書き方
Enumerable.Rangeの基本構文は次のとおりです。
C#Enumerable.Range(start, count)
startには開始する整数を指定します。countには生成する要素数を指定します。
たとえば、次のコードは10から始まる連番を3個生成します。
C#var numbers = Enumerable.Range(10, 3);
foreach (var number in numbers)
{
Console.WriteLine(number);
}
実行結果は次のとおりです。
C#10
11
12
2-2. 第1引数startは開始値を指定する
第1引数のstartは、生成される最初の値です。
C#var numbers = Enumerable.Range(5, 4);
この場合、最初の値は5です。生成される値は次のようになります。
C#5
6
7
8
startには正の数だけでなく、0や負の数も指定できます。
C#var numbers = Enumerable.Range(-3, 5);
この場合は、次の連番が生成されます。
C#-3
-2
-1
0
1
2-3. 第2引数countは生成する要素数を指定する
第2引数のcountは、終了値ではありません。生成する要素数です。
C#var numbers = Enumerable.Range(1, 10);
これは「1から10まで」ではなく、「1から始まる10個の数値」を意味します。
結果として、1から10までの数値が生成されます。
C#1, 2, 3, 4, 5, 6, 7, 8, 9, 10
一方、次のコードは5から10までを生成するわけではありません。
C#var numbers = Enumerable.Range(5, 10);
これは「5から始まる10個の数値」なので、結果は次のようになります。
C#5, 6, 7, 8, 9, 10, 11, 12, 13, 14
2-4. 戻り値はIEnumerable<int>である
Enumerable.Rangeの戻り値はIEnumerable<int>です。
C#IEnumerable<int> numbers = Enumerable.Range(1, 5);
IEnumerable<int>は、順番に値を取り出せる整数の列を表します。
そのため、foreachで順番に処理できます。
C#foreach (int number in numbers)
{
Console.WriteLine(number);
}
また、必要に応じてToList()やToArray()でリストや配列に変換できます。
C#List<int> list = Enumerable.Range(1, 5).ToList();
int[] array = Enumerable.Range(1, 5).ToArray();
2-5. startとcountを混同しやすいポイント
Enumerable.Rangeで最も多いつまずきは、countを終了値だと思ってしまうことです。
たとえば、10から20までの数値を作りたい場合、次のように書くと間違いです。
C#var numbers = Enumerable.Range(10, 20);
このコードは、10から始まる20個の数値を生成します。つまり、10から29までになります。
10から20までを生成したい場合は、個数を計算する必要があります。
C#var numbers = Enumerable.Range(10, 11);
10から20までには、10、11、12、13、14、15、16、17、18、19、20の11個があります。
終了値を含めたい場合は、次のように計算できます。
C#int start = 10;
int end = 20;
var numbers = Enumerable.Range(start, end - start + 1);
3. Enumerable.Rangeの基本的な使い方
3-1. 1から10までの連番を生成する
1から10までの連番を作るには、次のように書きます。
C#var numbers = Enumerable.Range(1, 10);
foreach (var number in numbers)
{
Console.WriteLine(number);
}
startが1、countが10なので、1から始まる10個の整数が生成されます。
C#1
2
3
4
5
6
7
8
9
10
3-2. 0から始まる連番を生成する
プログラミングでは、配列やリストのインデックスのように0から始まる数値を扱うことがよくあります。
C#var indexes = Enumerable.Range(0, 5);
foreach (var index in indexes)
{
Console.WriteLine(index);
}
実行結果は次のとおりです。
C#0
1
2
3
4
Enumerable.Range(0, 5)は、0から始まる5個の数値を生成します。
3-3. 任意の数値から連番を生成する
Enumerable.Rangeは、任意の整数から連番を生成できます。
C#var numbers = Enumerable.Range(100, 5);
foreach (var number in numbers)
{
Console.WriteLine(number);
}
実行結果は次のようになります。
C#100
101
102
103
104
ページ番号、商品番号、ランキング順位など、任意の開始値から連番を作りたい場合に便利です。
3-4. foreachでEnumerable.Rangeを処理する
Enumerable.RangeはIEnumerable<int>を返すため、foreachでそのまま処理できます。
C#foreach (var i in Enumerable.Range(1, 3))
{
Console.WriteLine($"{i}回目の処理です");
}
実行結果は次のとおりです。
C#1回目の処理です
2回目の処理です
3回目の処理です
指定回数だけ処理したいときにも使えます。
C#foreach (var _ in Enumerable.Range(0, 5))
{
Console.WriteLine("同じ処理を実行します");
}
変数の値を使わない場合は、_を使うと「値は使わない」という意図を表せます。
3-5. ToListやToArrayでコレクションに変換する
Enumerable.Rangeの結果は、必要に応じてリストや配列に変換できます。
C#var list = Enumerable.Range(1, 5).ToList();
var array = Enumerable.Range(1, 5).ToArray();
リストにすると、要素の追加や削除などができます。
C#var list = Enumerable.Range(1, 5).ToList();
list.Add(6);
foreach (var number in list)
{
Console.WriteLine(number);
}
配列にすると、固定長のデータとして扱えます。
C#int[] array = Enumerable.Range(1, 5).ToArray();
Console.WriteLine(array[0]);
4. foreach・for文・LINQと組み合わせた実践例
4-1. foreachで繰り返し処理を書く例
Enumerable.Rangeはforeachと相性が良いです。
C#foreach (var number in Enumerable.Range(1, 5))
{
Console.WriteLine($"現在の数値: {number}");
}
実行結果は次のとおりです。
C#現在の数値: 1
現在の数値: 2
現在の数値: 3
現在の数値: 4
現在の数値: 5
繰り返しの回数と使う数値が明確なので、処理の意図がわかりやすくなります。
4-2. for文の代わりにEnumerable.Rangeを使う例
for文で次のような処理を書くことがあります。
C#for (int i = 1; i <= 3; i++)
{
Console.WriteLine($"{i}回目");
}
これをEnumerable.Rangeで書くと、次のようになります。
C#foreach (var i in Enumerable.Range(1, 3))
{
Console.WriteLine($"{i}回目");
}
ただし、すべてのfor文をEnumerable.Rangeに置き換える必要はありません。単純なカウンター制御であれば、for文のほうが自然に読める場合もあります。
4-3. Selectで連番を加工する例
Selectを使うと、生成した連番を別の形に変換できます。
C#var squares = Enumerable.Range(1, 5)
.Select(x => x * x);
foreach (var square in squares)
{
Console.WriteLine(square);
}
実行結果は次のとおりです。
C#1
4
9
16
25
文字列に変換することもできます。
C#var labels = Enumerable.Range(1, 3)
.Select(x => $"No.{x}");
foreach (var label in labels)
{
Console.WriteLine(label);
}
実行結果は次のようになります。
C#No.1
No.2
No.3
4-4. Whereで条件に合う数値だけ抽出する例
Whereを使うと、条件に合う数値だけを抽出できます。
C#var evenNumbers = Enumerable.Range(1, 10)
.Where(x => x % 2 == 0);
foreach (var number in evenNumbers)
{
Console.WriteLine(number);
}
実行結果は次のとおりです。
C#2
4
6
8
10
奇数だけを取り出す場合は、条件を変えます。
C#var oddNumbers = Enumerable.Range(1, 10)
.Where(x => x % 2 != 0);
4-5. Sum・Average・Countなど集計処理に使う例
Enumerable.Rangeで生成した数値は、LINQの集計メソッドと組み合わせられます。
C#var numbers = Enumerable.Range(1, 10);
int sum = numbers.Sum();
double average = numbers.Average();
int count = numbers.Count();
Console.WriteLine(sum);
Console.WriteLine(average);
Console.WriteLine(count);
実行結果は次のようになります。
C#55
5.5
10
条件を指定して集計することもできます。
C#var evenSum = Enumerable.Range(1, 10)
.Where(x => x % 2 == 0)
.Sum();
Console.WriteLine(evenSum);
実行結果は次のとおりです。
C#30
5. Enumerable.Rangeでよくあるつまずきとエラー
5-1. countに終了値を指定してしまう間違い
Enumerable.Rangeで最もよくある間違いは、countに終了値を指定してしまうことです。
C#var numbers = Enumerable.Range(1, 100);
このコードは、1から100までを作る場合には正しいです。なぜなら、1から始まる100個の数値は1から100だからです。
しかし、次のコードは注意が必要です。
C#var numbers = Enumerable.Range(50, 100);
これは50から100までではありません。50から始まる100個の数値なので、50から149までになります。
50から100までを生成したいなら、次のように書きます。
C#var numbers = Enumerable.Range(50, 51);
終了値を変数で扱う場合は、次のように書くと間違いにくくなります。
C#int start = 50;
int end = 100;
var numbers = Enumerable.Range(start, end - start + 1);
5-2. 負のcountを指定すると例外になる
countに負の値を指定すると例外が発生します。
C#var numbers = Enumerable.Range(1, -5);
このようなコードは実行できません。
countは生成する要素数なので、0以上の値を指定する必要があります。
C#var empty = Enumerable.Range(1, 0);
countが0の場合は、空のシーケンスが生成されます。値は1つも含まれません。
C#foreach (var number in empty)
{
Console.WriteLine(number);
}
このコードでは何も出力されません。
5-3. startに負の値を指定する場合の動き
startには負の値を指定できます。
C#var numbers = Enumerable.Range(-5, 5);
foreach (var number in numbers)
{
Console.WriteLine(number);
}
実行結果は次のとおりです。
C#-5
-4
-3
-2
-1
countは負にできませんが、startは負の値でも問題ありません。
0をまたぐ連番も作れます。
C#var numbers = Enumerable.Range(-2, 5);
この場合、生成される値は次のようになります。
C#-2
-1
0
1
2
5-4. 生成範囲がintの上限を超える場合の注意点
Enumerable.Rangeはint型の連番を生成します。そのため、生成範囲がintの範囲を超えるような指定はできません。
たとえば、非常に大きな開始値から大量の数値を生成しようとすると、範囲外になる可能性があります。
C#var numbers = Enumerable.Range(int.MaxValue - 2, 3);
このコードでは、次の値が生成されます。
C#2147483645
2147483646
2147483647
しかし、さらに多くの個数を指定してint.MaxValueを超えるような範囲になると、例外が発生します。
巨大な範囲を扱う場合は、開始値と個数の関係に注意しましょう。
5-5. foreachで値が期待どおりにならない原因
foreachで値が期待どおりにならない場合、多くはstartとcountの指定ミスです。
C#foreach (var i in Enumerable.Range(0, 10))
{
Console.WriteLine(i);
}
このコードの出力は0から10ではなく、0から9です。
C#0
1
2
3
4
5
6
7
8
9
0から10まで出力したい場合は、11個の値が必要です。
C#foreach (var i in Enumerable.Range(0, 11))
{
Console.WriteLine(i);
}
「開始値から終了値まで」を作る場合は、end - start + 1で個数を計算するのが基本です。
5-6. 遅延実行による挙動を理解する
Enumerable.Rangeの戻り値はIEnumerable<int>です。LINQの多くの処理と同じように、実際に値が必要になるまで処理は実行されません。
C#var numbers = Enumerable.Range(1, 5)
.Select(x =>
{
Console.WriteLine($"処理中: {x}");
return x * 2;
});
この時点では、まだSelectの中の処理は実行されません。
C#foreach (var number in numbers)
{
Console.WriteLine($"結果: {number}");
}
foreachで列挙したときに、初めて処理が実行されます。
必要なタイミングで結果を確定させたい場合は、ToList()やToArray()を使います。
C#var numbers = Enumerable.Range(1, 5)
.Select(x => x * 2)
.ToList();
6. Enumerable.Rangeの応用パターン
6-1. インデックス付きの処理に使う
Enumerable.Rangeは、インデックス付きの処理に使えます。
C#var names = new List<string> { "Alice", "Bob", "Charlie" };
foreach (var i in Enumerable.Range(0, names.Count))
{
Console.WriteLine($"{i}: {names[i]}");
}
実行結果は次のとおりです。
C#0: Alice
1: Bob
2: Charlie
リストの要素番号を明示的に使いたい場合に便利です。
6-2. 配列やリストの要素番号を処理する
配列のインデックスを使って、要素を加工することもできます。
C#var scores = new[] { 80, 90, 75 };
var results = Enumerable.Range(0, scores.Length)
.Select(i => $"No.{i + 1}: {scores[i]}点");
foreach (var result in results)
{
Console.WriteLine(result);
}
実行結果は次のようになります。
C#No.1: 80点
No.2: 90点
No.3: 75点
Enumerable.Range(0, scores.Length)により、配列のインデックスとして使える0、1、2を生成しています。
6-3. 同じ処理を指定回数だけ実行する
値そのものを使わず、指定回数だけ処理を実行したい場合にも使えます。
C#foreach (var _ in Enumerable.Range(0, 3))
{
Console.WriteLine("処理を実行しました");
}
実行結果は次のとおりです。
C#処理を実行しました
処理を実行しました
処理を実行しました
ただし、このような単純な繰り返しではfor文のほうが読みやすい場合もあります。
C#for (int i = 0; i < 3; i++)
{
Console.WriteLine("処理を実行しました");
}
チームのコーディング方針や可読性に合わせて使い分けましょう。
6-4. 日付の連続データを生成する
Enumerable.Rangeは整数を生成するメソッドですが、Selectと組み合わせることで日付の連続データも作れます。
C#var startDate = new DateTime(2026, 1, 1);
var dates = Enumerable.Range(0, 7)
.Select(i => startDate.AddDays(i));
foreach (var date in dates)
{
Console.WriteLine(date.ToString("yyyy/MM/dd"));
}
実行結果は次のようになります。
C#2026/01/01
2026/01/02
2026/01/03
2026/01/04
2026/01/05
2026/01/06
2026/01/07
カレンダー表示や期間内の日付一覧を作るときに役立ちます。
6-5. 文字列やオブジェクトのリストを生成する
Enumerable.Rangeで作った連番をもとに、文字列のリストを作れます。
C#var items = Enumerable.Range(1, 5)
.Select(i => $"商品{i}")
.ToList();
foreach (var item in items)
{
Console.WriteLine(item);
}
実行結果は次のとおりです。
C#商品1
商品2
商品3
商品4
商品5
オブジェクトのリストを作ることもできます。
C#var users = Enumerable.Range(1, 3)
.Select(i => new
{
Id = i,
Name = $"User{i}"
})
.ToList();
foreach (var user in users)
{
Console.WriteLine($"{user.Id}: {user.Name}");
}
実行結果は次のようになります。
C#1: User1
2: User2
3: User3
6-6. テストデータやサンプルデータを作成する
テスト用のデータをまとめて作りたいときにも、Enumerable.Rangeは便利です。
C#var testUsers = Enumerable.Range(1, 10)
.Select(i => new User
{
Id = i,
Name = $"テストユーザー{i}",
Email = $"user{i}@example.com"
})
.ToList();
public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
}
手作業で10件のデータを書くよりも、短く読みやすく作成できます。
7. Enumerable.Rangeを使うべき場面・使わない方がよい場面
7-1. 連番生成やLINQ処理に向いている場面
Enumerable.Rangeは、連番をデータとして扱う場面に向いています。
たとえば、次のような処理です。
C#var pageNumbers = Enumerable.Range(1, totalPages);
ページ番号の生成、ランキング順位の生成、日付一覧の生成、テストデータの作成、LINQでの加工や抽出などでは、Enumerable.Rangeを使うとコードがすっきりします。
7-2. 単純な繰り返しならfor文が読みやすい場面
単純に「10回処理する」だけなら、for文のほうが読みやすい場合があります。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
これをEnumerable.Rangeで書くと、次のようになります。
C#foreach (var i in Enumerable.Range(0, 10))
{
Console.WriteLine(i);
}
どちらも正しく動きますが、単純なループではfor文のほうが多くのC#開発者にとって自然に見えることがあります。
7-3. パフォーマンスを意識したい場面
Enumerable.Rangeは便利ですが、LINQを多用すると、場面によってはfor文よりオーバーヘッドが発生することがあります。
大量データを高頻度で処理する場合や、パフォーマンスが重要な処理では、for文のほうが適していることがあります。
C#for (int i = 0; i < array.Length; i++)
{
array[i] *= 2;
}
配列を直接更新するような処理では、for文のほうがシンプルで効率的です。
一方、データの生成や変換を宣言的に書きたい場合は、Enumerable.RangeとLINQが向いています。
7-4. 可読性を下げないための使い分け
Enumerable.Rangeを使うとコードを短くできますが、短ければ必ず読みやすいわけではありません。
たとえば、次のようにLINQをつなげすぎると、何をしているのかわかりにくくなることがあります。
C#var result = Enumerable.Range(1, 100)
.Where(x => x % 2 == 0)
.Select(x => x * x)
.Where(x => x > 1000)
.Sum();
この程度なら読めますが、条件や変換が複雑になる場合は、途中結果を変数に分けると読みやすくなります。
C#var evenNumbers = Enumerable.Range(1, 100)
.Where(x => x % 2 == 0);
var squares = evenNumbers.Select(x => x * x);
var result = squares.Where(x => x > 1000)
.Sum();
7-5. チーム開発で迷わない判断基準
チーム開発では、個人の好みよりも読みやすさと一貫性が重要です。
Enumerable.Rangeを使うか迷った場合は、次のように考えるとよいでしょう。
連番をデータとして扱うならEnumerable.Range、単純な繰り返しならfor文、LINQと組み合わせて加工するならEnumerable.Range、配列やリストを直接更新するならfor文が向いています。
チーム内でLINQに慣れている人が多ければEnumerable.Rangeは自然に読めますが、初心者が多い場合はfor文のほうが理解しやすいこともあります。
8. Enumerable.Rangeと似た処理との違い
8-1. for文との違い
for文は、繰り返し処理を書くための構文です。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
Enumerable.Rangeは、連続した整数のシーケンスを生成するメソッドです。
C#var numbers = Enumerable.Range(0, 5);
for文は処理の制御に向いており、Enumerable.Rangeは数値の列を作って扱うことに向いています。
8-2. while文との違い
while文は、条件がtrueの間だけ処理を繰り返します。
C#int i = 0;
while (i < 5)
{
Console.WriteLine(i);
i++;
}
繰り返し回数が明確な場合は、while文よりfor文やEnumerable.Rangeのほうが読みやすいことが多いです。
while文は、終了条件が状況によって変わる処理に向いています。
C#while (userInput != "exit")
{
userInput = Console.ReadLine();
}
一方、Enumerable.Rangeは「1から10まで」「0から4まで」のように、あらかじめ範囲が決まっている場合に向いています。
8-3. Enumerable.Repeatとの違い
Enumerable.Rangeと似たメソッドにEnumerable.Repeatがあります。
Enumerable.Rangeは連続した整数を生成します。
C#var numbers = Enumerable.Range(1, 5);
結果は次のようになります。
C#1, 2, 3, 4, 5
一方、Enumerable.Repeatは同じ値を指定回数だけ繰り返します。
C#var values = Enumerable.Repeat("Hello", 3);
結果は次のようになります。
C#Hello
Hello
Hello
連番を作りたいならEnumerable.Range、同じ値を繰り返したいならEnumerable.Repeatを使います。
8-4. Range構文との違い
C#には、配列や文字列などの一部を取り出すためのRange構文もあります。
C#var array = new[] { 10, 20, 30, 40, 50 };
var part = array[1..4];
この場合、partには次の要素が入ります。
C#20, 30, 40
Enumerable.Rangeは連番を生成するメソッドです。
C#var numbers = Enumerable.Range(1, 4);
結果は次のようになります。
C#1, 2, 3, 4
名前は似ていますが、役割は異なります。Enumerable.Rangeは数値の列を作り、Range構文は範囲指定で要素を取り出します。
8-5. Pythonのrangeとの違い
Pythonにもrangeがあります。
Pythonrange(1, 5)
Pythonのrange(1, 5)は、1から4までを表します。終了値の5は含まれません。
一方、C#のEnumerable.Range(1, 5)は、1から始まる5個の数値を生成します。
C#Enumerable.Range(1, 5)
結果は次のとおりです。
C#1, 2, 3, 4, 5
Pythonのrangeに慣れている人は、C#の第2引数を終了値だと勘違いしやすいので注意しましょう。
9. Enumerable.Rangeの実務で使えるサンプルコード集
9-1. ページ番号を生成する
ページネーションでページ番号を生成する例です。
C#int totalPages = 5;
var pages = Enumerable.Range(1, totalPages);
foreach (var page in pages)
{
Console.WriteLine($"ページ {page}");
}
実行結果は次のとおりです。
C#ページ 1
ページ 2
ページ 3
ページ 4
ページ 5
開始ページを変更したい場合は、startを変えます。
C#int startPage = 6;
int pageCount = 5;
var pages = Enumerable.Range(startPage, pageCount);
この場合、6から10までのページ番号が生成されます。
9-2. カレンダーの日付一覧を作る
指定した日付から1週間分の日付を生成する例です。
C#var startDate = new DateTime(2026, 6, 1);
var week = Enumerable.Range(0, 7)
.Select(i => startDate.AddDays(i));
foreach (var date in week)
{
Console.WriteLine(date.ToString("yyyy年MM月dd日"));
}
実行結果は次のようになります。
C#2026年06月01日
2026年06月02日
2026年06月03日
2026年06月04日
2026年06月05日
2026年06月06日
2026年06月07日
月の日数分の日付を作ることもできます。
C#int year = 2026;
int month = 6;
int days = DateTime.DaysInMonth(year, month);
var dates = Enumerable.Range(1, days)
.Select(day => new DateTime(year, month, day));
9-3. ランキング順位を表示する
ランキング順位を表示する例です。
C#var names = new List<string> { "佐藤", "鈴木", "高橋" };
var ranking = Enumerable.Range(0, names.Count)
.Select(i => $"{i + 1}位: {names[i]}");
foreach (var item in ranking)
{
Console.WriteLine(item);
}
実行結果は次のとおりです。
C#1位: 佐藤
2位: 鈴木
3位: 高橋
インデックスは0から始まるため、順位として表示するときはi + 1にしています。
9-4. 複数行のダミーデータを作る
開発中やテスト中に、複数件のダミーデータを作りたい場合があります。
C#var products = Enumerable.Range(1, 5)
.Select(i => new Product
{
Id = i,
Name = $"商品{i}",
Price = i * 1000
})
.ToList();
foreach (var product in products)
{
Console.WriteLine($"{product.Id}: {product.Name} - {product.Price}円");
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int Price { get; set; }
}
実行結果は次のようになります。
C#1: 商品1 - 1000円
2: 商品2 - 2000円
3: 商品3 - 3000円
4: 商品4 - 4000円
5: 商品5 - 5000円
9-5. インデックスと値を組み合わせて出力する
リストの値とインデックスを組み合わせて出力する例です。
C#var fruits = new List<string> { "Apple", "Banana", "Orange" };
var results = Enumerable.Range(0, fruits.Count)
.Select(i => $"{i}: {fruits[i]}");
foreach (var result in results)
{
Console.WriteLine(result);
}
実行結果は次のとおりです。
C#0: Apple
1: Banana
2: Orange
LINQのSelectにはインデックス付きのオーバーロードもあるため、次のようにも書けます。
C#var results = fruits.Select((fruit, index) => $"{index}: {fruit}");
このように、用途によってEnumerable.RangeとLINQの機能を使い分けるとよいでしょう。
10. Enumerable.Rangeに関するよくある質問
10-1. Enumerable.Rangeで1から100まで作るには?
1から100まで作るには、次のように書きます。
C#var numbers = Enumerable.Range(1, 100);
startが1、countが100なので、1から始まる100個の整数が生成されます。
foreachで出力する場合は次のとおりです。
C#foreach (var number in Enumerable.Range(1, 100))
{
Console.WriteLine(number);
}
10-2. Enumerable.Rangeで降順の連番は作れる?
Enumerable.Range自体は昇順の連番を生成します。降順にしたい場合は、Reverse()を組み合わせます。
C#var numbers = Enumerable.Range(1, 10)
.Reverse();
foreach (var number in numbers)
{
Console.WriteLine(number);
}
実行結果は次のようになります。
C#10
9
8
7
6
5
4
3
2
1
10から1までを作りたい場合は、この書き方が簡単です。
別の方法として、Selectで計算することもできます。
C#var numbers = Enumerable.Range(0, 10)
.Select(i => 10 - i);
10-3. Enumerable.Rangeで小数やlong型は扱える?
Enumerable.Rangeが生成するのはint型の整数です。そのため、小数やlong型の連番を直接生成することはできません。
小数を作りたい場合は、Selectで変換します。
C#var values = Enumerable.Range(0, 5)
.Select(i => i * 0.5);
foreach (var value in values)
{
Console.WriteLine(value);
}
実行結果は次のようになります。
C#0
0.5
1
1.5
2
long型として扱いたい場合も、Selectで変換します。
C#var values = Enumerable.Range(1, 5)
.Select(i => (long)i);
ただし、Enumerable.Rangeの開始値と個数はintの範囲で指定する必要があります。
10-4. Enumerable.Rangeはメモリを大量に使う?
Enumerable.RangeはIEnumerable<int>を返し、基本的には必要になったタイミングで値を順番に生成します。そのため、作成しただけで大量の配列やリストがすぐに確保されるわけではありません。
C#var numbers = Enumerable.Range(1, 1000000);
この時点で100万個の整数を格納したリストが作られるわけではありません。
ただし、ToList()やToArray()を使うと、すべての値をメモリ上に展開します。
C#var list = Enumerable.Range(1, 1000000).ToList();
大量データを扱う場合は、必要がなければToList()やToArray()を避け、foreachやLINQで順番に処理するとよいでしょう。
10-5. Enumerable.Rangeはどの名前空間で使える?
Enumerable.Rangeを使うには、System.Linq名前空間が必要です。
C#using System.Linq;
通常のC#プロジェクトでは、テンプレートや環境によって最初から使える場合もあります。使えない場合は、ファイルの先頭にusing System.Linq;を追加してください。
C#using System;
using System.Linq;
class Program
{
static void Main()
{
foreach (var number in Enumerable.Range(1, 5))
{
Console.WriteLine(number);
}
}
}
まとめ
C#のEnumerable.Rangeは、指定した開始値から連続する整数を生成できる便利なメソッドです。
基本構文は次のとおりです。
C#Enumerable.Range(start, count)
startは開始値、countは生成する要素数です。特にcountを終了値と間違えやすいため注意が必要です。
1から10まで作りたい場合は、次のように書きます。
C#var numbers = Enumerable.Range(1, 10);
0から始まるインデックスを作りたい場合は、次のように書きます。
C#var indexes = Enumerable.Range(0, count);
Enumerable.Rangeは、foreachでの繰り返し、LINQのSelectやWhere、Sumなどの集計処理、日付一覧の生成、テストデータ作成など、さまざまな場面で使えます。
一方で、単純な繰り返しや配列の直接更新では、for文のほうが読みやすく効率的な場合もあります。
連番をデータとして扱いたいときはEnumerable.Range、処理の流れを直接制御したいときはfor文、というように使い分けると、C#のコードをより読みやすく書けます。

