Я бы посоветовал вам начать с создания функций GetEnumeratorInFirstStyle, GetEnumeratorInSecondStyle и т. Д. (Конечно же, использовать имена, подходящие для вашего приложения), а затем создать новые структуры, например (например, в синтаксисе vb, но их легко можно преобразовать в C #):
Class enumTest
Function GetEnumeratorInFirstStyle() As IEnumerator(Of Integer)
Return Enumerable.Empty(Of Integer)() ' Real code would do something better
End Function
Private Structure FirstStyleEnumerable
Implements IEnumerable(Of Integer)
Private myEnumTest As enumTest
Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of Integer) Implements System.Collections.Generic.IEnumerable(Of Integer).GetEnumerator
Return myEnumTest.GetEnumeratorInFirstStyle
End Function
Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Return myEnumTest.GetEnumeratorInFirstStyle
End Function
Sub New(ByVal newEnumTest As enumTest)
myEnumTest = newEnumTest
End Sub
End Structure
Public ReadOnly Property AsFirstStyleEnumerable As IEnumerable(Of Integer)
Get
Return New FirstStyleEnumerable(Me)
End Get
End Property
End Class
Обратите внимание, что используется структура, а не класс, поскольку использование класса потребует создания нового объекта кучи и добавления дополнительного уровня косвенности к его доступу;настоящая цель структуры - позволить ей реализовать «отличный» IEnumerable от инкапсулированного объекта.Кстати, было бы возможно использовать обобщения с классами маркеров, чтобы избежать необходимости вручную определять новую структуру FirstStyleEnumerator для каждого варианта перечисления.Я не уверен, что это будет чище или более запутанно.
Interface IQualifiedEnumerable(Of T, U)
Function GetEnumerator() As IEnumerable(Of U)
End Interface
Structure QualifiedEnumerableWrapper(Of T, U)
Implements IEnumerable(Of U)
Private myEnumerable As IQualifiedEnumerable(Of T, U)
Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of U) Implements System.Collections.Generic.IEnumerable(Of U).GetEnumerator
Return myEnumerable.GetEnumerator
End Function
Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Return myEnumerable.GetEnumerator
End Function
Sub New(ByVal newEnumerable As IQualifiedEnumerable(Of T, U))
myEnumerable = newEnumerable
End Sub
End Structure
Class EnumTest2
Implements IQualifiedEnumerable(Of FirstEnumerationStyle, Integer)
Implements IQualifiedEnumerable(Of SecondEnumerationStyle, Integer)
Private Class FirstEnumerationStyle ' Marker classes for generics
End Class
Private Class SecondEnumerationStyle
End Class
Private Function GetFirstStyleEnumerator() As System.Collections.Generic.IEnumerable(Of Integer) Implements IQualifiedEnumerable(Of FirstEnumerationStyle, Integer).GetEnumerator
Return Enumerable.Empty(Of Integer)()
End Function
Private Function GetSecondStyleEnumerator() As System.Collections.Generic.IEnumerable(Of Integer) Implements IQualifiedEnumerable(Of SecondEnumerationStyle, Integer).GetEnumerator
Return Enumerable.Empty(Of Integer)()
End Function
Public ReadOnly Property AsFirstStyleEnumerable As IEnumerable(Of Integer)
Get
Return New QualifiedEnumerableWrapper(Of FirstEnumerationStyle, Integer)
End Get
End Property
Public ReadOnly Property AsSecondStyleEnumerable As IEnumerable(Of Integer)
Get
Return New QualifiedEnumerableWrapper(Of SecondEnumerationStyle, Integer)
End Get
End Property
End Class
Здесь определения интерфейса и структуры полностью универсальны;добавление каждого дополнительного метода перечисления в класс потребовало бы добавления функции для возврата ее перечислителя и свойства для возврата QualifiedEnumerableWrapper соответствующего типа.