在以下代码中,
For Each item in MyCollection
...
Next
编译器使用什么来确定item
的类型?
例如,假设我有这个继承非泛型集合的类
Public Class BaseDataObjectGenericCollection(Of T)
Inherits BaseDataObjectCollection
End Class
每个循环的A仍然将Item类型推断为Object
。我如何修改上面的类以使类型推断工作?
编辑:Per Beatles1692的回答,实现IEnumerator(Of T)有点起作用。基类已经有GetEnumerator
函数,继承自CollectionBase
,所以我的实现看起来像这样,
Public Function GetEnumerator1() As System.Collections.Generic.IEnumerator(Of T) Implements System.Collections.Generic.IEnumerable(Of T).GetEnumerator
Return MyBase.Cast(Of T)().GetEnumerator
End Function
但是,for循环仍然将类型推断为对象。但是,如果我将接口实现更改为此,
Public Shadows Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of T) Implements System.Collections.Generic.IEnumerable(Of T).GetEnumerator
Return MyBase.Cast(Of T)().GetEnumerator
End Function
这样做,for循环得到类型推断正确。所以我想现在的问题是,For Each
只是寻找一个名为GetEnumerator
的函数吗?
答案 0 :(得分:1)
你应该写:
For Each Item As SpecificType In MyCollection
....
Next
然后它会在每个循环中将Item转换为SpecificType,或者你的集合应该已经实现了IEnumerable(Of T)
答案 1 :(得分:1)
嗯,这样的问题只有一个地方可以去。规范!
第10.9.3节讨论For Each语句。根据它:
[if]正在使用局部变量类型推断,然后标识符定义一个新的局部变量,其范围是整个For循环,其类型是集合的元素类型(如果枚举器表达式被键入为Object,则为Object)
“集合”在这里看起来很模糊,但它在下一页上精确定义。本质上,类型必须具有GetEnumerator()调用,并且此枚举器必须(a)具有返回布尔类型的MoveNext()
方法,并且(b)具有Current
属性。 Current属性的类型是编译器将推断的类型。注意它实际上与IEnumerator或IEnumerable无关......你只需要符合规定的模式。请考虑以下代码:
Option Infer On
Public Module M
Sub Main()
For Each x In New SomeClass()
Next
End Sub
End Module
Public Class SomeClass
Public Function GetEnumerator() As MyEnumerator
Return New MyEnumerator()
End Function
End Class
Public Class MyEnumerator
Public ReadOnly Property Current As Integer
Get
Return 42
End Get
End Property
Public Function MoveNext() As Boolean
Return True
End Function
End Class
Sub Main()中的“x”类型是Integer,因为Current属性返回Integer。