IEnumerable<T>.GetEnumerator メソッド
定義
重要
一部の情報は、リリース前に大きく変更される可能性があるプレリリースされた製品に関するものです。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。
コレクションを反復処理する列挙子を返します。
public:
System::Collections::Generic::IEnumerator<T> ^ GetEnumerator();
public System.Collections.Generic.IEnumerator<out T> GetEnumerator ();
public System.Collections.Generic.IEnumerator<T> GetEnumerator ();
abstract member GetEnumerator : unit -> System.Collections.Generic.IEnumerator<'T>
Public Function GetEnumerator () As IEnumerator(Of Out T)
Public Function GetEnumerator () As IEnumerator(Of T)
戻り値
コレクションの反復処理に使用できる列挙子。
例
次の例では、 インターフェイスを実装し、その実装を IEnumerable<T> 使用して LINQ クエリを作成する方法を示します。 を実装IEnumerable<T>する場合は、 または も実装IEnumerator<T>する必要があります。C# の場合のみ、yield キーワード (keyword)を使用できます。 実装 IEnumerator<T> も実装する必要 IDisposable があります。この例で説明します。
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class App
{
// Exercise 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(disposing: 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(disposing: 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(disposing:=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(disposing:=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
注釈
返される IEnumerator<T> は、プロパティ を公開することによってコレクションを反復処理する機能を Current 提供します。列挙子を使用してコレクション内のデータを読み取ることができますが、コレクションを変更することはできません。
最初、列挙子はコレクションの先頭の要素の前に位置付けられます。 この位置では、Current が未定義です。 そのため、Current の値を読み取る前に、MoveNext メソッドを呼び出し、列挙子をコレクションの最初の要素に進める必要があります。
Currentは、次の要素に対する設定CurrentとしてMoveNext再び呼び出されるまでMoveNext、同じオブジェクトを返します。
MoveNext がコレクションの末尾を通過した場合、列挙子がコレクション内の最後の要素の後に配置され、MoveNext は false
を返します。 列挙子がこの位置にある場合、後続の MoveNext 呼び出しも false
を返します。 が返された false
Current の最後のMoveNext呼び出しが未定義の場合。 Current を、再度、コレクションの最初の要素に設定することはできません。列挙子の新しいインスタンスを作成する必要があります。
要素の追加、変更、削除など、コレクションに変更が加えられた場合、列挙子の動作は未定義です。
列挙子にはコレクションへの排他的アクセス権がないため、コレクションが変更されていない限り、列挙子は有効なままです。 要素の追加、変更、削除など、コレクションに変更が加えられた場合、列挙子は無効になり、予期しない結果が発生する可能性があります。 また、コレクションの列挙はスレッド セーフなプロシージャではありません。 スレッド セーフを保証するには、列挙子の間にコレクションをロックするか、コレクションに同期を実装する必要があります。
名前空間内のコレクションの既定の System.Collections.Generic 実装は同期されません。
適用対象
こちらもご覧ください
.NET