
C#インデックス付きforeach(開発者向けの仕組み)
C#では、foreach文は通常、配列、リスト、その他の列挙可能な型のようなコレクションを繰り返し処理するために使用されます。しかし、foreach ループには、現在の反復を追跡するための組み込みインデックス変数がないという制約があります。 開発者は、現在の要素のインデックスにアクセスする必要があります。 以下では、この機能とIronPDFライブラリを実装するさまざまな方法を探ります。
foreachループの基本
foreachループは、IEnumerableを実装する配列、リスト、辞書、その他の型の反復処理を簡素化するように設計されています。 foreach文を使って整数データ型の配列をループ処理する基本的な例を示します:
int[] numbers = { 10, 20, 30, 40 };
foreach (int number in numbers)
{
Console.WriteLine(number);
}Dim numbers() As Integer = { 10, 20, 30, 40 }
For Each number As Integer In numbers
Console.WriteLine(number)
Next numberこの例では、number は各イテレーション中にコレクションの要素を表します。 ループは自動的に配列のすべての要素を繰り返し処理します。 しかし、現在の要素のインデックスにアクセスする組み込みの方法はありません。
foreachループでインデックスを処理する
C#はforeachループでインデックスを直接提供しませんが、いくつかのテクニックで解決できます。 これらの方法について詳しく説明しましょう。
方法1: 別の変数を使用する
現在の要素のインデックスを取得する最も簡単な方法の1つは、外部インデックス変数を使用することです。 ループ内で手動でインクリメントする必要があります:
int[] numbers = { 10, 20, 30, 40 };
int numberIndex = 0;
foreach (int number in numbers)
{
Console.WriteLine($"Index: {numberIndex}, Value: {number}");
numberIndex++;
}Dim numbers() As Integer = { 10, 20, 30, 40 }
Dim numberIndex As Integer = 0
For Each number As Integer In numbers
Console.WriteLine($"Index: {numberIndex}, Value: {number}")
numberIndex += 1
Next numberこのコードでは、index変数はループ開始前に初期化され、各反復中にループ内でインクリメントされます。 このアプローチは有効ですが、手作業でインデックスを維持する必要があり、必ずしも理想的ではありません。
方法2: LINQのSelectメソッドを使う
LINQ の Select メソッドを使用して、コレクションの各要素をそのインデックスを含む新しい形式に投影できます。 以下は例です:
int[] numbers = { 10, 20, 30, 40 };
foreach (var item in numbers.Select((value, index) => new { value, index }))
{
Console.WriteLine($"Index: {item.index}, Value: {item.value}");
}Dim numbers() As Integer = { 10, 20, 30, 40 }
For Each item In numbers.Select(Function(value, index) New With {
Key value,
Key index
})
Console.WriteLine($"Index: {item.index}, Value: {item.value}")
Next itemこの例では、Select が現在の要素の値とそのインデックスの両方を含む匿名オブジェクトを作成します。 foreachループは、これらのオブジェクトを繰り返し処理し、インデックスと値の両方に直接アクセスできます。
方法 3: カスタム イテレーターを使用する
yield return キーワードを使用してカスタムイテレーター拡張メソッドを実装し、現在の要素とそのインデックスを生成するメソッドを作成できます。 これは少し高度ですが、柔軟なソリューションを提供します。
public static IEnumerable<(int index, T value)> WithIndex<t>(this IEnumerable<t> source)
{
int index = 0;
foreach (T value in source)
{
yield return (index, value);
index++;
}
}Imports System.Collections.Generic
Public Module Extensions
<System.Runtime.CompilerServices.Extension>
Public Iterator Function WithIndex(Of T)(source As IEnumerable(Of T)) As IEnumerable(Of (index As Integer, value As T))
Dim index As Integer = 0
For Each value As T In source
Yield (index, value)
index += 1
Next
End Function
End Moduleこれで、あなたのコレクションでこの拡張メソッドを使用できます:
int[] numbers = { 10, 20, 30, 40 };
foreach (var (index, value) in numbers.WithIndex())
{
Console.WriteLine($"Index: {index}, Value: {value}");
}Dim numbers() As Integer = { 10, 20, 30, 40 }
foreach var(index, value) In numbers.WithIndex()
Console.WriteLine($"Index: {index}, Value: {value}")
Nextこのアプローチでは、手作業によるインデックス管理を再利用可能なメソッドに抽象化することで、foreach with index問題に対するよりエレガントなソリューションを作成します。
インデックスにアクセスするために while ループを使用する
配列やリストのようなコレクションを扱う場合、インデックス変数と組み合わせてwhileループを使用すると、インデックスと現在の要素の両方にアクセスできます:
int[] numbers = { 10, 20, 30, 40 };
int index = 0;
while (index < numbers.Length)
{
Console.WriteLine($"Index: {index}, Value: {numbers[index]}");
index++;
}Dim numbers() As Integer = { 10, 20, 30, 40 }
Dim index As Integer = 0
Do While index < numbers.Length
Console.WriteLine($"Index: {index}, Value: {numbers(index)}")
index += 1
Loop
この方法では、インデックス変数を配列またはリストの添え字として使用することで、インデックスと現在の要素の両方に直接アクセスできます。
.NETにおけるカスタム コレクションとイテレータ
カスタマイズされたコレクションを使用している場合は、インデックス付きアクセスをサポートするイテレータを実装することができます。 IEnumerable インターフェースを実装し、yield return ステートメントを使用することで、要素とそのインデックスの両方を返すイテレーターを作成できます。
IEnumerableを実装したカスタムコレクションを作成する例を示します:
public class CustomCollection<t> : IEnumerable<t>
{
private T[] _items;
public CustomCollection(T[] items)
{
_items = items;
}
public IEnumerator<t> GetEnumerator()
{
for (int i = 0; i < _items.Length; i++)
{
yield return _items[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}Imports System.Collections
Imports System.Collections.Generic
Public Class CustomCollection(Of T)
Implements IEnumerable(Of T)
Private _items As T()
Public Sub New(items As T())
_items = items
End Sub
Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
For i As Integer = 0 To _items.Length - 1
Yield _items(i)
Next
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
End Classそして、foreachループでこのカスタムコレクションを使用することができます:
var customCollection = new CustomCollection<int>(new int[] { 10, 20, 30, 40 });
foreach (int number in customCollection)
{
Console.WriteLine(number);
}Dim customCollection As New CustomCollection(Of Integer)(New Integer() { 10, 20, 30, 40 })
For Each number As Integer In customCollection
Console.WriteLine(number)
Next numberGetEnumerator メソッドを実装し、yield return を使用することで、.NET の他の任意のコレクションと同様に、foreach ループがカスタムコレクションと共に動作することを可能にするイテレーターを作成します。
辞書を使用し、キーと値のペアを反復する
辞書を扱う場合、foreachループを使えば、キーと値のペアを直接反復処理することができます。 これは、各反復中にキーと値の両方にアクセスする一般的なユースケースです:
Dictionary<int, string> dict = new Dictionary<int, string>
{
{ 1, "Apple" },
{ 2, "Banana" },
{ 3, "Cherry" }
};
foreach (var kvp in dict)
{
Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
}Dim dict As New Dictionary(Of Integer, String) From {
{1, "Apple"},
{2, "Banana"},
{3, "Cherry"}
}
For Each kvp In dict
Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}")
Next kvpこの例では、kvp.Key は現在のキーを提供し、kvp.Value は現在の値を提供します。
IronPDF を C# の foreach ループとインデックスで使用する

IronPDFはHTMLからのPDF生成やその他のPDF関連のタスクをC#で処理するためのPDFライブラリです。 最新 for .NET Frameworkにも対応しています。 IronPDFを使ってPDFを生成するとき、データのコレクションを繰り返し処理し、PDFファイルに動的にコンテンツを挿入する必要があるかもしれません。foreachループをインデックス処理と組み合わせることで、コレクション内の現在のアイテムのインデックスに基づいて、位置決め、番号付け、カスタムロジックを管理することができます。 IronPDFを使ってPDFを作成し、コレクションの各アイテムをインデックスとともにドキュメントに挿入する例を示します。
using IronPdf;
class Program
{
static void Main(string[] args)
{
// Create a new PDF document renderer
var pdf = new ChromePdfRenderer();
// Sample data array
string[] items = { "First Item", "Second Item", "Third Item" };
// Initialize the HTML content with foreach loop and index
string htmlContent = "<html><body>";
int index = 0;
foreach (var item in items)
{
htmlContent += $"<h2>Item {index + 1}: {item}</h2>";
index++;
}
htmlContent += "</body></html>";
// Render the HTML to PDF
var pdfDocument = pdf.RenderHtmlAsPdf(htmlContent);
// Save the PDF document
pdfDocument.SaveAs("output.pdf");
// Notify completion
Console.WriteLine("PDF created successfully with indexed items.");
}
}Imports IronPdf
Class Program
Shared Sub Main(ByVal args As String())
' Create a new PDF document renderer
Dim pdf = New ChromePdfRenderer()
' Sample data array
Dim items As String() = {"First Item", "Second Item", "Third Item"}
' Initialize the HTML content with foreach loop and index
Dim htmlContent As String = "<html><body>"
Dim index As Integer = 0
For Each item In items
htmlContent += $"<h2>Item {index + 1}: {item}</h2>"
index += 1
Next item
htmlContent += "</body></html>"
' Render the HTML to PDF
Dim pdfDocument = pdf.RenderHtmlAsPdf(htmlContent)
' Save the PDF document
pdfDocument.SaveAs("output.pdf")
' Notify completion
Console.WriteLine("PDF created successfully with indexed items.")
End Sub
End Classこちらが出力されたPDFファイルです:

結論

C#では、foreachループはコレクションを繰り返し処理する便利な方法ですが、インデックスのネイティブサポートがありません。 しかし、この制限を克服する方法はいくつかあります。 シンプルなインデックス変数、LINQ の Select メソッド、またはカスタムイテレーターを使用するかにかかわらず、イテレーション中に現在または次の要素のインデックスにアクセスできます。 これらのテクニックを理解することで、特に各要素のインデックスを知る必要がある場合に、foreachループをより効率的に使用することができます。
IronPDFを使えば、すぐにコミットする必要はありません。 私たちは、無料トライアルを提供しており、ソフトウェアの機能を詳しく調べることができます。 気に入った場合、ライセンスは $999 から始まります。

Jacob Mellor is Chief Technology Officer at Iron Software and a visionary engineer pioneering C# PDF technology. As the original developer behind Iron Software's core codebase, he has shaped the company's product architecture since its inception, transforming it alongside CEO Cameron Rimington into a 50+ person company serving NASA, Tesla, and global government agencies.
Related Articles


