问题描述
在以下代码中,
对于MyCollection中的每个项目
...
下一个
编译器用于确定项目$ c $的类型例如,假设我有这个类,它继承了一个非泛型集合,
<$ p
$ p $ 公共类BaseDataObjectGenericCollection(Of T)
继承BaseDataObjectCollection
结束类
每个循环的A依然推断Item类型为 Object
。编辑:每Beatles1692的答案,实现IEnumerator(Of T)有点作品。如何修改上面的类,以使类型推断工作?
GetEnumerator
函数,继承自 CollectionBase
,所以我的实现看起来像这样, Public Function GetEnumerator1()As System.Collections.Generic.IEnumerator(Of T)Implements System.Collections.Generic.IEnumerable(Of T) .GetEnumerator
返回MyBase.Cast(Of T)()。GetEnumerator
End Function
然而,for循环仍然会将该类型推断为对象。但是,如果我将接口实现更改为此,
Public Shadows Function GetEnumerator()As System.Collections.Generic.IEnumerator (T)实现System.Collections.Generic.IEnumerable(Of T).GetEnumerator
返回MyBase.Cast(Of T)()。GetEnumerator
End Function
这可以起作用,for循环获得正确的类型推断。所以我想现在的问题是, For Each
只需寻找一个名为 GetEnumerator
?
好吧,只有一个地方可以解决这个问题。规范!
第10.9.3节讨论For Each语句。根据它:
collection这里看起来很模糊,但是它在下一页精确定义。实质上,该类型必须具有GetEnumerator()调用,并且该枚举器必须(a)具有返回布尔类型的 MoveNext()
方法,并且(b)具有当前
属性。 Current属性的类型是由编译器推断的类型。请注意,它实际上与IEnumerator或IEnumerable无关......你只需要符合规定的模式。考虑下面的代码:
选项推断
$ b公共模块M
Sub Main()
For Each x In New SomeClass()
Next
End Sub
End Module
Public Class SomeClass
Public Function GetEnumerator()作为MyEnumerator
返回新的MyEnumerator()
结束函数
结束类
公共类MyEnumerator
公共ReadOnly属性当前As整数
获取
返回42
结束获取
结束属性
公共函数MoveNext()作为布尔
返回True
End函数
结束类
Sub Main()中的x类型是Integer ,因为Current属性返回Integer。
In the following code,
For Each item in MyCollection
...
Next
What does the compiler use to determine the type of item
?
For example let say I have this class, which is inheriting a non generic collection,
Public Class BaseDataObjectGenericCollection(Of T)
Inherits BaseDataObjectCollection
End Class
A for each loop still infers the Item type as Object
. How would I have to modify the above class to make the type inference work?
Edit: Per Beatles1692's answer, Implementing IEnumerator(Of T) kinda works. The base class already has a GetEnumerator
function, inherited from CollectionBase
, so I my implementation looked like this,
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
However, the for loop still infers the type as object. But, if I change the interface implementation to this,
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
That works, the for loop gets the type inference correct. So I guess the question is now, does For Each
just look for a function called GetEnumerator
?
Well, there's only one place to go for a question like this. The spec!
Section 10.9.3 discusses For Each statements. According to it:
"collection" here seems vague, but it's precisely defined on the next page. Essentially, the type must have a GetEnumerator() call, and this enumerator must (a) have a MoveNext()
method that returns a boolean type, and (b) have a Current
property. The type of the Current property is the type that will be inferred by the compiler. Note it actually has nothing to do with IEnumerator or IEnumerable...you just have to fit the prescribed pattern. Consider this code:
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
The type of "x" in the Sub Main() is Integer, since the Current property returns Integer.
这篇关于每个循环的VB.Net是怎样看待推断类型的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!