IEnumerable<T>.GetEnumerator Méthode
Définition
Retourne un énumérateur qui itère au sein de la collection.Returns an enumerator that iterates through the collection.
public:
System::Collections::Generic::IEnumerator<T> ^ GetEnumerator();
public System.Collections.Generic.IEnumerator<T> GetEnumerator ();
abstract member GetEnumerator : unit -> System.Collections.Generic.IEnumerator<'T>
Public Function GetEnumerator () As IEnumerator(Of T)
Retours
Énumérateur permettant d'effectuer une itération au sein de la collection.An enumerator that can be used to iterate through the collection.
Exemples
L’exemple suivant montre comment implémenter l’interface IEnumerable<T> et utilise cette implémentation pour créer une requête LINQ.The following example demonstrates how to implement the IEnumerable<T> interface and uses that implementation to create a LINQ query. Lorsque vous implémentez IEnumerable<T>, vous devez également implémenter IEnumerator<T> ou C# , pour uniquement, vous pouvez utiliser le mot clé yield .When you implement IEnumerable<T>, you must also implement IEnumerator<T> or, for C# only, you can use the yield keyword. L’implémentation de IEnumerator<T> nécessite également l’implémentation de IDisposable, ce que vous verrez dans cet exemple.Implementing IEnumerator<T> also requires IDisposable to be implemented, which you will see in this example.
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class App
{
// Excercise the Iterator and show that it's more
// performant.
public static void Main()
{
TestStreamReaderEnumerable();
Console.WriteLine("---");
TestReadingFile();
}
public static void TestStreamReaderEnumerable()
{
// Check the memory before the iterator is used.
long memoryBefore = GC.GetTotalMemory(true);
IEnumerable<String> stringsFound;
// Open a file with the StreamReaderEnumerable and check for a string.
try {
stringsFound =
from line in new StreamReaderEnumerable(@"c:\temp\tempFile.txt")
where line.Contains("string to search for")
select line;
Console.WriteLine("Found: " + stringsFound.Count());
}
catch (FileNotFoundException) {
Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
return;
}
// Check the memory after the iterator and output it to the console.
long memoryAfter = GC.GetTotalMemory(false);
Console.WriteLine("Memory Used With Iterator = \t"
+ string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
}
public static void TestReadingFile()
{
long memoryBefore = GC.GetTotalMemory(true);
StreamReader sr;
try {
sr = File.OpenText("c:\\temp\\tempFile.txt");
}
catch (FileNotFoundException) {
Console.WriteLine(@"This example requires a file named C:\temp\tempFile.txt.");
return;
}
// Add the file contents to a generic list of strings.
List<string> fileContents = new List<string>();
while (!sr.EndOfStream) {
fileContents.Add(sr.ReadLine());
}
// Check for the string.
var stringsFound =
from line in fileContents
where line.Contains("string to search for")
select line;
sr.Close();
Console.WriteLine("Found: " + stringsFound.Count());
// Check the memory after when the iterator is not used, and output it to the console.
long memoryAfter = GC.GetTotalMemory(false);
Console.WriteLine("Memory Used Without Iterator = \t" +
string.Format(((memoryAfter - memoryBefore) / 1000).ToString(), "n") + "kb");
}
}
// A custom class that implements IEnumerable(T). When you implement IEnumerable(T),
// you must also implement IEnumerable and IEnumerator(T).
public class StreamReaderEnumerable : IEnumerable<string>
{
private string _filePath;
public StreamReaderEnumerable(string filePath)
{
_filePath = filePath;
}
// Must implement GetEnumerator, which returns a new StreamReaderEnumerator.
public IEnumerator<string> GetEnumerator()
{
return new StreamReaderEnumerator(_filePath);
}
// Must also implement IEnumerable.GetEnumerator, but implement as a private method.
private IEnumerator GetEnumerator1()
{
return this.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator1();
}
}
// When you implement IEnumerable(T), you must also implement IEnumerator(T),
// which will walk through the contents of the file one line at a time.
// Implementing IEnumerator(T) requires that you implement IEnumerator and IDisposable.
public class StreamReaderEnumerator : IEnumerator<string>
{
private StreamReader _sr;
public StreamReaderEnumerator(string filePath)
{
_sr = new StreamReader(filePath);
}
private string _current;
// Implement the IEnumerator(T).Current publicly, but implement
// IEnumerator.Current, which is also required, privately.
public string Current
{
get
{
if (_sr == null || _current == null)
{
throw new InvalidOperationException();
}
return _current;
}
}
private object Current1
{
get { return this.Current; }
}
object IEnumerator.Current
{
get { return Current1; }
}
// Implement MoveNext and Reset, which are required by IEnumerator.
public bool MoveNext()
{
_current = _sr.ReadLine();
if (_current == null)
return false;
return true;
}
public void Reset()
{
_sr.DiscardBufferedData();
_sr.BaseStream.Seek(0, SeekOrigin.Begin);
_current = null;
}
// Implement IDisposable, which is also implemented by IEnumerator(T).
private bool disposedValue = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
// Dispose of managed resources.
}
_current = null;
if (_sr != null) {
_sr.Close();
_sr.Dispose();
}
}
this.disposedValue = true;
}
~StreamReaderEnumerator()
{
Dispose(false);
}
}
// This example displays output similar to the following:
// Found: 2
// Memory Used With Iterator = 33kb
// ---
// Found: 2
// Memory Used Without Iterator = 206kb
Imports System.IO
Imports System.Collections
Imports System.Collections.Generic
Imports System.Linq
Public Module App
' Excercise the Iterator and show that it's more performant.
Public Sub Main()
TestStreamReaderEnumerable()
Console.WriteLine("---")
TestReadingFile()
End Sub
Public Sub TestStreamReaderEnumerable()
' Check the memory before the iterator is used.
Dim memoryBefore As Long = GC.GetTotalMemory(true)
Dim stringsFound As IEnumerable(Of String)
' Open a file with the StreamReaderEnumerable and check for a string.
Try
stringsFound =
from line in new StreamReaderEnumerable("c:\temp\tempFile.txt")
where line.Contains("string to search for")
select line
Console.WriteLine("Found: {0}", stringsFound.Count())
Catch e As FileNotFoundException
Console.WriteLine("This example requires a file named C:\temp\tempFile.txt.")
Return
End Try
' Check the memory after the iterator and output it to the console.
Dim memoryAfter As Long = GC.GetTotalMemory(false)
Console.WriteLine("Memory Used with Iterator = {1}{0} kb",
(memoryAfter - memoryBefore)\1000, vbTab)
End Sub
Public Sub TestReadingFile()
Dim memoryBefore As Long = GC.GetTotalMemory(true)
Dim sr As StreamReader
Try
sr = File.OpenText("c:\temp\tempFile.txt")
Catch e As FileNotFoundException
Console.WriteLine("This example requires a file named C:\temp\tempFile.txt.")
Return
End Try
' Add the file contents to a generic list of strings.
Dim fileContents As New List(Of String)()
Do While Not sr.EndOfStream
fileContents.Add(sr.ReadLine())
Loop
' Check for the string.
Dim stringsFound =
from line in fileContents
where line.Contains("string to search for")
select line
sr.Close()
Console.WriteLine("Found: {0}", stringsFound.Count())
' Check the memory after when the iterator is not used, and output it to the console.
Dim memoryAfter As Long = GC.GetTotalMemory(False)
Console.WriteLine("Memory Used without Iterator = {1}{0} kb",
(memoryAfter - memoryBefore)\1000, vbTab)
End Sub
End Module
' A custom class that implements IEnumerable(T). When you implement IEnumerable(T),
' you must also implement IEnumerable and IEnumerator(T).
Public Class StreamReaderEnumerable : Implements IEnumerable(Of String)
Private _filePath As String
Public Sub New(filePath As String)
_filePath = filePath
End Sub
' Must implement GetEnumerator, which returns a new StreamReaderEnumerator.
Public Function GetEnumerator() As IEnumerator(Of String) _
Implements IEnumerable(Of String).GetEnumerator
Return New StreamReaderEnumerator(_filePath)
End Function
' Must also implement IEnumerable.GetEnumerator, but implement as a private method.
Private Function GetEnumerator1() As IEnumerator _
Implements IEnumerable.GetEnumerator
Return Me.GetEnumerator()
End Function
End Class
' When you implement IEnumerable(T), you must also implement IEnumerator(T),
' which will walk through the contents of the file one line at a time.
' Implementing IEnumerator(T) requires that you implement IEnumerator and IDisposable.
Public Class StreamReaderEnumerator : Implements IEnumerator(Of String)
Private _sr As StreamReader
Public Sub New(filePath As String)
_sr = New StreamReader(filePath)
End Sub
Private _current As String
' Implement the IEnumerator(T).Current Publicly, but implement
' IEnumerator.Current, which is also required, privately.
Public ReadOnly Property Current As String _
Implements IEnumerator(Of String).Current
Get
If _sr Is Nothing OrElse _current Is Nothing
Throw New InvalidOperationException()
End If
Return _current
End Get
End Property
Private ReadOnly Property Current1 As Object _
Implements IEnumerator.Current
Get
Return Me.Current
End Get
End Property
' Implement MoveNext and Reset, which are required by IEnumerator.
Public Function MoveNext() As Boolean _
Implements IEnumerator.MoveNext
_current = _sr.ReadLine()
if _current Is Nothing Then Return False
Return True
End Function
Public Sub Reset() _
Implements IEnumerator.Reset
_sr.DiscardBufferedData()
_sr.BaseStream.Seek(0, SeekOrigin.Begin)
_current = Nothing
End Sub
' Implement IDisposable, which is also implemented by IEnumerator(T).
Private disposedValue As Boolean = False
Public Sub Dispose() _
Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' Dispose of managed resources.
End If
_current = Nothing
If _sr IsNot Nothing Then
_sr.Close()
_sr.Dispose()
End If
End If
Me.disposedValue = True
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
End Sub
End Class
' This example displays output similar to the following:
' Found: 2
' Memory Used With Iterator = 33kb
' ---
' Found: 2
' Memory Used Without Iterator = 206kb
Pour obtenir C# un autre exemple qui montre comment implémenter l’interface IEnumerable<T>, consultez l' exemple génériques.For another C# example that demonstrates how to implement the IEnumerable<T> interface, see the Generics Sample. Cet exemple utilise le mot clé yield
au lieu d’implémenter IEnumerator<T>.This sample uses of the yield
keyword instead of implementing IEnumerator<T>.
Remarques
Le @no__t retourné-0 donne la possibilité d’itérer au sein de la collection en exposant une propriété Current. Vous pouvez utiliser des énumérateurs pour lire les données d’une collection, mais pas pour modifier la collection.The returned IEnumerator<T> provides the ability to iterate through the collection by exposing a Current property .You can use enumerators to read the data in a collection, but not to modify the collection.
Au départ, l'énumérateur est positionné avant le premier élément de la collection.Initially, the enumerator is positioned before the first element in the collection. À cette position, Current n'est pas défini.At this position, Current is undefined. Par conséquent, vous devez appeler la méthode MoveNext pour avancer l’énumérateur jusqu’au premier élément de la collection avant de lire la valeur de Current.Therefore, you must call the MoveNext method to advance the enumerator to the first element of the collection before reading the value of Current.
Current retourne le même objet jusqu’à ce que MoveNext soit appelée à nouveau, car MoveNext définit Current sur l’élément suivant.Current returns the same object until MoveNext is called again as MoveNext sets Current to the next element.
Si MoveNext passe la fin de la collection, l’énumérateur est positionné après le dernier élément de la collection et MoveNext retourne false
.If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false
. Lorsque l’énumérateur se trouve à cette position, les appels suivants à MoveNext retournent également false
.When the enumerator is at this position, subsequent calls to MoveNext also return false
. Si le dernier appel à MoveNext a retourné false
, Current n’est pas défini.If the last call to MoveNext returned false
, Current is undefined. Vous ne pouvez pas attribuer de nouveau Current au premier élément de la collection ; vous devez créer une nouvelle instance de l’énumérateur à la place.You cannot set Current to the first element of the collection again; you must create a new enumerator instance instead.
Si des modifications sont apportées à la collection, telles que l’ajout, la modification ou la suppression d’éléments, le comportement de l’énumérateur n’est pas défini.If changes are made to the collection, such as adding, modifying, or deleting elements, the behavior of the enumerator is undefined.
Un énumérateur ne dispose pas d’un accès exclusif à la collection, de sorte qu’un énumérateur reste valide tant que la collection reste inchangée.An enumerator does not have exclusive access to the collection so an enumerator remains valid as long as the collection remains unchanged. Si des modifications sont apportées à la collection, telles que l’ajout, la modification ou la suppression d’éléments, l’énumérateur n’est pas valide et vous pouvez obtenir des résultats inattendus.If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is invalidated and you may get unexpected results. En outre, l’énumération d’une collection n’est pas une procédure thread-safe.Also, enumerating a collection is not a thread-safe procedure. Pour garantir la sécurité des threads, vous devez verrouiller la collection pendant l’énumérateur ou implémenter la synchronisation sur la collection.To guarantee thread-safety, you should lock the collection during enumerator or implement synchronization on the collection.
Les implémentations par défaut de collections dans l’espace de noms System.Collections.Generic ne sont pas synchronisées.Default implementations of collections in the System.Collections.Generic namespace aren't synchronized.