generic <typename T>
public interface class IEnumerable : System::Collections::IEnumerable
public interface IEnumerable<out T> : System.Collections.IEnumerable
public interface IEnumerable<T> : System.Collections.IEnumerable
type seq<'T> = interface
interface IEnumerable
Public Interface IEnumerable(Of Out T)
Implements IEnumerable
Public Interface IEnumerable(Of T)
Implements IEnumerable
以下示例演示如何实现
IEnumerable<T>
接口以及如何使用该实现来创建 LINQ 查询。 实现
IEnumerable<T>
时,还必须实现
IEnumerator<T>
或,仅对于 C#,可以使用
yield
关键字。 实现
IEnumerator<T>
还需要
IDisposable
实现,你将在本示例中看到这一点。
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
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.
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
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())
' 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
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
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
IEnumerable<T>
是 命名空间中
System.Collections.Generic
集合(例如 、
Dictionary<TKey,TValue>
和
Stack<T>
)
List<T>
和其他泛型集合(如
ObservableCollection<T>
和
ConcurrentStack<T>
)的基接口。 可以使用 语句枚举实现
IEnumerable<T>
的
foreach
集合。
有关此接口的非泛型版本,请参阅
System.Collections.IEnumerable
。
IEnumerable<T>
包含实现此接口时必须实现的单个方法;
GetEnumerator
,返回
IEnumerator<T>
对象。 返回的
IEnumerator<T>
提供通过公开
Current
属性循环访问集合的功能。
实施者说明
为了保持与循环访问非泛型集合的方法兼容,
IEnumerable<T>
实现
IEnumerable
。 这允许将泛型集合传递到需要对象
IEnumerable
的方法。
ToImmutableDictionary<TSource,TKey,TValue>(IEnumerable<TSource>,
Func<TSource,TKey>, Func<TSource,TValue>, IEqualityComparer<TKey>,
IEqualityComparer<TValue>)
枚举并转换序列,然后使用指定的键和值比较器生成其内容的不可变字典。
GroupBy<TSource,TKey,TElement,TResult>(IEnumerable<TSource>, Func<TSource,
TKey>, Func<TSource,TElement>, Func<TKey,IEnumerable<TElement>,
TResult>, IEqualityComparer<TKey>)
根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。 通过使用指定的比较器对键值进行比较,并且通过使用指定的函数对每个组的元素进行投影。
GroupJoin<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>,
Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,IEnumerable<TInner>,
TResult>)
基于键值等同性对两个序列的元素进行关联,并对结果进行分组。 使用默认的相等比较器对键进行比较。
GroupJoin<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>,
Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,IEnumerable<TInner>,
TResult>, IEqualityComparer<TKey>)
基于键值等同性对两个序列的元素进行关联,并对结果进行分组。 使用指定的
IEqualityComparer<T>
对键进行比较。
Join<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>,
Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>,
IEqualityComparer<TKey>)
基于匹配键对两个序列的元素进行关联。 使用指定的
IEqualityComparer<T>
对键进行比较。