在VB中实现IEnumerable的方法 [英] Ways of implenting IEnumerable in VB
问题描述
好的,我无法理解经典(也许是长篇大论)的做法,多个班级和新收益率路线(显然)是否相同。
我能理解经典路线(我认为),请看下面的代码。
如果我理解,产量会让我感到困惑。它是正确的然后它是绝对的天才,我得到一个状态机的想法(我认为)和逻辑上它有点意义但我完全没有信心。
可能这么简单吗?你只需要根据你的情况做一个简单或复杂的方法吗?
(警告,愚蠢的例子,因为数组已经可以枚举,但很容易演示) < pre lang =vb> 公共 类 YieldExample
Implements IEnumerable
私有 _Thing 作为 Double ()
公共 Iterator 功能 GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
If IsNothing( Me ._ Thing)然后
抛出 新 InvalidO perationException()
结束 如果
对于索引作为 整数 = 0 我 ._ Thing.GetUpperBound( 0 )
收益率 Me ._ Thing(Index)
Next
结束 功能
结束 班级
我理解为老路。
公共 类 ExampleEnumerable
实现 IEnumerable( of Double )
Private _Thing As Double ()
公共 Function GetEnumerator() as IEnumerator( of Double ) Implements IEnumerable( of Double )。GetEnumerator
返回 新 ExampleEnumerator(我 ._ Thing)
结束 功能
公共 功能 GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
返回 我 .GetEnumerator
结束 功能
结束 类
公共 类 ExampleEnumerator
实现 IEnumerator( Double )
私有 _Thing 正如 Double ()
私有 _Index 作为 整数
私有 _curItem 作为 Double
公共 Sub 新( ByVal 事情作为 Double ())
Me ._ Thing = Thing
Me ._Index = -1
我 ._ curItem = 没什么
< span class =code-keyword>结束 Sub
公开 ReadOnly 属性当前作为 Double Implements IEnumerator( of Double )。当前
获取
如果 IsNothing( Me ._ curItem)然后
抛出 新 InvalidOperationException()
结束 如果
返回 我 ._ curItem
结束 获取
结束 财产
公共 ReadOnly 属性 Current1 正如 对象 Implements IEnumerator.Current
获取
返回 我 .Current
结束 获取
结束 属性
公共 功能 MoveNext() As Boolean Implements IEnumerator。 MoveNext
' 如果我们已经在最后那么返回false
如果 我 ._ Index = 我 ._ Thing.GetUpperBound ( 0 )然后
返回 错误
结束 如果
' 否则移至数组中的下一个位置
Me 。 _Index + = 1
我 ._ curItem = 我 ._ Thing( Me ._ Index)
返回 True
结束 功能
公共 Sub 重置()实施 IEnumerator.Reset
Me ._ Index = -1
Me ._ curItem = < span class =code-keyword> Nothing
结束 Sub
#RegionIDisposable支持
结束 类
谢谢,
迈克
如果有人偶然发现这个,那么我最终回答了自己的问题问题,是产量是编写自己的枚举器的一种非常快捷方便的捷径,在大多数情况下,这可能至少同样有效。如果编写枚举器,编译器只会将yield转换为与它创建的代码非常相似的代码,因此在引擎盖下几乎没有什么区别,除非在特定情况下或者每毫秒计数一次(在这种情况下你可能)无论如何可能都在编写自己的汇编程序。)
选择你的普查员& Me.Understand Yield和IEnumerable(C#) [ ^ ]
选择你的普查员& Me.Understand Yield和IEnumerable(VB) [ ^ ]
Mike
OK, I cannot get my head around the whether there is a difference between the 'classic' (perhaps long winded) way of doing it, multiple classes and the 'new' Yield route to (apparently) the same end.
I can understand the classic route (I think), see the code below.
Yield confuses the heck out of me, if I understand it correctly then it's absolutely genius, I get the idea of a state machine (I think) and logically it sort of makes sense but I am not at all confident.
Can it possibly be this simple? You just make that one method as simple or complex as necessary for your situation?
(Warning, silly example since arrays can already be enumerated, but it's easy to demo)
Public Class YieldExample
Implements IEnumerable
Private _Thing As Double()
Public Iterator Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
If IsNothing(Me._Thing) Then
Throw New InvalidOperationException()
End If
For Index As Integer = 0 To Me._Thing.GetUpperBound(0)
Yield Me._Thing(Index)
Next
End Function
End Class
What I understand to be the 'old way'.
Public Class ExampleEnumerable
Implements IEnumerable(Of Double)
Private _Thing As Double()
Public Function GetEnumerator() As IEnumerator(Of Double) Implements IEnumerable(Of Double).GetEnumerator
Return New ExampleEnumerator(Me._Thing)
End Function
Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Return Me.GetEnumerator
End Function
End Class
Public Class ExampleEnumerator
Implements IEnumerator(Of Double)
Private _Thing As Double()
Private _Index As Integer
Private _curItem As Double
Public Sub New(ByVal Thing As Double())
Me._Thing = Thing
Me._Index = -1
Me._curItem = Nothing
End Sub
Public ReadOnly Property Current As Double Implements IEnumerator(Of Double).Current
Get
If IsNothing(Me._curItem) Then
Throw New InvalidOperationException()
End If
Return Me._curItem
End Get
End Property
Public ReadOnly Property Current1 As Object Implements IEnumerator.Current
Get
Return Me.Current
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
'If we are already at the end then return false
If Me._Index = Me._Thing.GetUpperBound(0) Then
Return False
End If
'Otherwise move to the next position in the array
Me._Index += 1
Me._curItem = Me._Thing(Me._Index)
Return True
End Function
Public Sub Reset() Implements IEnumerator.Reset
Me._Index = -1
Me._curItem = Nothing
End Sub
#Region "IDisposable Support"
End Class
Thanks,
Mike
If anyone ever stumbles into this then I ended up answering my own question, yes yield is a very quick and easy shortcut to writing your own enumerator and in the majority of cases is probably at least as effective. The compiler simply turns yield into very similar code to that which it creates if you write the enumerator, so 'under the hood' there is very little difference, except possibly in specific cases or when every millisecond counts perhaps (in which case you'd probably be writing your own assembler anyway).
Pick Your Enumerator & Me.Understand Yield and IEnumerable (C#)[^]
Pick Your Enumerator & Me.Understand Yield and IEnumerable (VB)[^]
Mike
这篇关于在VB中实现IEnumerable的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!