.NET ヘルプ

C# foreach with index (開発者のための仕組み)

公開済み 2024年10月23日
共有:

C#では、foreach文は通常、配列、リスト、その他の列挙可能な型のようなコレクションを反復処理するために使用されます。しかし、foreachループには、現在の反復を追跡するための組み込みのインデックス変数がないという制約がある。 開発者は、現在の要素のインデックスにアクセスする必要があります。 以下では、この機能を実装するためのさまざまな方法と、その方法について説明します。IronPDFライブラリ.

foreachループの基本

foreachループは、IEnumerableを実装する配列、リスト、辞書、その他の型の反復処理を簡素化するように設計されています。 foreach文を使って整数データ型の配列をループ処理する基本的な例を示します:

int[] numbers = { 10, 20, 30, 40 };
foreach (int number in numbers)
{
    Console.WriteLine(number);
}
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
VB   C#

この例では、数字は、各反復中のコレクションの要素を表しています。 ループは自動的に配列のすべての要素を繰り返し処理します。 しかし、現在の要素のインデックスにアクセスする組み込みの方法はありません。

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++;
}
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
VB   C#

このコードでは、index変数はループ開始前に初期化され、各反復中にループ内でインクリメントされます。 このアプローチは有効ですが、手作業でインデックスを維持する必要があり、必ずしも理想的ではありません。

方法2:LINQのSelectメソッドを使う

LINQのSelectメソッドを使用すると、コレクションの各要素を、そのインデックスを含む新しいフォームに投影することができます。 Here's an example: 例があります。

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}");
}
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
VB   C#

この例では、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++;
    }
}
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++;
    }
}
<System.Runtime.CompilerServices.Extension> _
Public Function WithIndex(Of T)(ByVal 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 value
End Function
VB   C#

これで、あなたのコレクションでこの拡張メソッドを使用できます:

int[] numbers = { 10, 20, 30, 40 };
foreach (var (index, value) in numbers.WithIndex())
{
    Console.WriteLine($"Index: {index}, Value: {value}");
}
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
VB   C#

このアプローチでは、手作業によるインデックス管理を再利用可能なメソッドに抽象化することで、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++;
}
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
VB   C#

C# インデックス付き foreach(開発者向けの仕組み):図1 - インデックスの出力

この方法では、インデックス変数を配列またはリストの添え字として使用することで、インデックスと現在の要素の両方に直接アクセスできます。

.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();
    }
}
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();
    }
}
Public Class CustomCollection(Of T)
	Implements IEnumerable(Of T)

	Private _items() As T
	Public Sub New(ByVal items() As T)
		_items = items
	End Sub
	Public Iterator Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
		For i As Integer = 0 To _items.Length - 1
			Yield _items(i)
		Next i
	End Function
	Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
		Return GetEnumerator()
	End Function
End Class
VB   C#

そして、foreachループでこのカスタムコレクションを使用することができます:

var customCollection = new CustomCollection<int>(new int[] { 10, 20, 30, 40 });
foreach (int number in customCollection)
{
    Console.WriteLine(number);
}
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 number
VB   C#

GetEnumeratorメソッドを実装し、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}");
}
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
VB   C#

この例では、kvp.Key が現在のキーを、kvp.Value が現在の値を示します。

C#とforeachループとインデックスでIronPdfを使う

C# インデックス付き foreach(開発者向けの仕組み):図2 - IronPDF

IronPDFはPDFを扱うためのライブラリです。HTMLからのPDF生成C# での PDF 関連の作業。 最新の.NET Frameworkにも対応しています。 IronPDFを使ってPDFを生成する場合、データのコレクションを繰り返し処理し、PDFファイルに動的にコンテンツを挿入する必要があるかもしれません。foreachループをインデックス処理と組み合わせることで、コレクション内の現在のアイテムのインデックスに基づいて、位置決め、番号付け、カスタムロジックを管理することができます。 IronPDFを使ってPDFを作成し、コレクションの各アイテムをインデックスとともにドキュメントに挿入する例を示します。

using IronPdf;
class Program
{
    static void Main(string[] args)
    {
        // Create a new PDF document
        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.");
    }
}
using IronPdf;
class Program
{
    static void Main(string[] args)
    {
        // Create a new PDF document
        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
Friend Class Program
	Shared Sub Main(ByVal args() As String)
		' Create a new PDF document
		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
VB   C#

こちらが出力されたPDFファイルです。

C# インデックス付き foreach(開発者向けの仕組み):図3 - PDF出力

結論

C# インデックス付き foreach(開発者向けの仕組み):図4 - ライセンス

C#では、foreachループはコレクションを繰り返し処理する便利な方法ですが、インデックスのネイティブサポートがありません。 しかし、この制限を克服する方法はいくつかあります。 単純なインデックス変数でも、LINQのSelectメソッドでも、カスタムのイテレータでも、反復処理中に現在または次の要素のインデックスにアクセスすることができます。 これらのテクニックを理解することで、特に各要素のインデックスを知る必要がある場合に、foreachループをより効率的に使用することができます。

IronPDFを使えば、すぐにコミットする必要はありません。 当社では無料試用また、ソフトウェアの機能を深く掘り下げることができるような翻訳が求められます。 気に入ったものがあれば、ライセンスは749ドルから。

< 以前
C# インデクサー(開発者のための仕組み)
次へ >
Socket io .NET(開発者向けの動作方法)