
C# foreach z indeksem (Jak to działa dla programistów)
W języku C# instrukcja foreach jest zazwyczaj używana do iteracji nad kolekcjami, takimi jak tablice, listy lub inne typy wyliczalne. Jednak jednym z ograniczeń jest to, że pętla foreach nie zapewnia wbudowanej zmiennej indeksowej do śledzenia bieżącej iteracji. Programiści często potrzebują dostępu do indeksu bieżącego elementu. Poniżej omówimy różne sposoby wdrożenia tej funkcjonalności oraz biblioteki IronPDF.
Podstawy pętli foreach
Pętla foreach została zaprojektowana w celu uproszczenia iteracji przez tablice, listy, słowniki i inne typy, które implementują interfejs IEnumerable. Oto podstawowy przykład wykorzystania instrukcji foreach do iteracji po tablicy danych typu integer:
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 numberW tym przykładzie number reprezentuje element kolekcji podczas każdej iteracji. Pętla automatycznie przechodzi przez wszystkie elementy tablicy. Nie ma jednak wbudowanego sposobu na uzyskanie dostępu do indeksu bieżącego elementu.
Obsługa indeksu w pętli foreach
Chociaż język C# nie udostępnia bezpośrednio indeksu w pętli foreach, istnieje kilka technik, które pozwalają rozwiązać ten problem. Omówmy te metody szczegółowo.
Metoda 1: Użycie oddzielnej zmiennej
Jednym z najprostszych sposobów uzyskania indeksu bieżącego elementu jest użycie zewnętrznej zmiennej indeksowej. Będziesz musiał zwiększać tę wartość ręcznie w pętli:
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 numberW tym kodzie zmienna index jest inicjowana przed rozpoczęciem pętli, a następnie zwiększana wewnątrz pętli podczas każdej iteracji. Chociaż takie podejście się sprawdza, wymaga ręcznego utrzymywania indeksu, co nie zawsze jest idealnym rozwiązaniem.
Metoda 2: Korzystanie z metody Select w LINQ
Metoda Select z LINQ może być użyta do projektowania każdego elementu kolekcji w nową formę, włączając jego indeks. Oto przykład:
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 itemW tym przykładzie Select tworzy anonimowy obiekt, który zawiera zarówno wartość bieżącego elementu, jak i jego indeks. Pętla foreach może następnie iterować po tych obiektach i uzyskać bezpośredni dostęp zarówno do indeksu, jak i wartości.
Metoda 3: Korzystanie z niestandardowego iteratora
Możesz zaimplementować niestandardową metodę rozszerzenia iteratora, używając słowa kluczowego yield return do stworzenia metody, która zwraca zarówno bieżący element, jak i jego indeks. Jest to nieco bardziej zaawansowane rozwiązanie, ale oferuje większą elastyczność.
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 ModuleTeraz możesz używać tej metody rozszerzenia w swoich kolekcjach:
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}")
NextTakie podejście stanowi bardziej eleganckie rozwiązanie problemu foreach z indeksem poprzez wyodrębnienie ręcznego zarządzania indeksem do metody wielokrotnego użytku.
Użycie pętli while do uzyskania dostępu do indeksów
Jeśli pracujesz z kolekcjami, takimi jak tablice lub listy, możesz użyć pętli while w połączeniu ze zmienną indeksową, aby uzyskać dostęp zarówno do indeksu, jak i bieżącego elementu:
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
Ta metoda pozwala na bezpośredni dostęp zarówno do indeksu, jak i do bieżącego elementu poprzez użycie zmiennej indeksu jako indeksu dolnego dla tablicy lub listy.
Niestandardowe kolekcje i iteratory w .NET
Jeśli pracujesz z niestandardowymi kolekcjami, możesz zaimplementować własne iteratory, aby obsługiwały dostęp indeksowany. Poprzez zaimplementowanie interfejsu IEnumerable i użycie instrukcji yield return, możesz tworzyć iteratory, które zwracają zarówno element, jak i jego indeks.
Oto przykład tworzenia niestandardowej kolekcji, która implementuje interfejs 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 ClassNastępnie można użyć tej niestandardowej kolekcji w pętli 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 numberPoprzez zaimplementowanie metody GetEnumerator i użycie yield return, tworzysz iterator, który pozwala pętli foreach współpracować z twoją niestandardową kolekcją tak jak z każdą inną kolekcją w .NET.
Korzystanie ze słowników i iteracja z parami klucz-wartość
Podczas pracy ze słownikami pętla foreach pozwala na bezpośrednie iterowanie po parach klucz-wartość. Jest to typowy przypadek użycia umożliwiający dostęp zarówno do klucza, jak i wartości podczas każdej iteracji:
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 kvpW tym przykładzie kvp.Key daje ci aktualny klucz, a kvp.Value daje ci aktualną wartość.
Uzycie IronPDF z petla foreach w C# i indeksem

IronPDF to biblioteka PDF służąca do generowania plików PDF z HTML oraz wykonywania innych zadań związanych z PDF w języku C#. Jest również kompatybilny z najnowszym .NET Framework. Podczas generowania plików PDF za pomocą IronPDF może zaistnieć potrzeba iteracji nad zbiorem danych i dynamicznego wstawiania treści do pliku PDF. Połączenie pętli foreach z obsługą indeksów pozwala zarządzać pozycjonowaniem, numeracją lub niestandardową logiką w oparciu o indeks bieżącego elementu w zbiorze. Oto praktyczny przykład wykorzystania IronPDF do utworzenia pliku PDF, w którym każdy element kolekcji jest wstawiany do dokumentu wraz z indeksem.
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 ClassOto plik PDF z tłumaczeniem:

Wnioski

W języku C# pętla foreach jest wygodnym sposobem iteracji nad kolekcjami, ale nie ma natywnej obsługi indeksowania. Istnieje jednak kilka sposobów na obejście tego ograniczenia. Niezależnie od tego, czy używasz prostego indeksu, metody Select z LINQ, czy niestandardowych iteratorów, możesz uzyskać dostęp do indeksu bieżącego lub następnego elementu podczas iteracji. Zrozumienie tych technik może pomóc w bardziej efektywnym wykorzystaniu pętli foreach, zwłaszcza gdy trzeba znać indeks każdego elementu.
Dzięki IronPDF nie musisz od razu podejmować decyzji. Oferujemy bezpłatną wersję próbną, która pozwala dogłębnie poznać możliwości oprogramowania. Jeśli podoba Ci się to, co widzisz, licencje zaczynają się od $999.

Jacob Mellor jest Chief Technology Officer w Iron Software i wizjonerskim inżynierem, pionierem technologii C# PDF. Jako pierwotny deweloper głównej bazy kodowej Iron Software, kształtuje architekturę produktów firmy od jej początku, przekształcając ją wspólnie z CEO Cameron Rimington w firmę liczącą ponad 50 osób, obsługującą NASA, Teslę i światowe agencje rządowe.
Powiązane artykuły


