Что VB.Net для каждого цикла смотрит на вывод типа - PullRequest
2 голосов
/ 21 февраля 2012

В следующем коде:

For Each item in MyCollection
...
Next

Что использует компилятор для определения типа item?

Например, допустим, у меня есть этот класс, который наследуетне универсальная коллекция,

Public Class BaseDataObjectGenericCollection(Of T)
    Inherits BaseDataObjectCollection
End Class

A для каждого цикла все еще выводит тип элемента как 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
        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?

Ответы [ 2 ]

1 голос
/ 21 февраля 2012

Ну, есть только одно место, чтобы пойти на такой вопрос. Спецификация!

Раздел 10.9.3 обсуждает для каждого утверждения. Согласно этому:

[если] используется вывод типа локальной переменной, то идентификатор определяет новую локальную переменную, область действия которой - весь цикл For, а тип - тип элемента коллекции (Object, если выражение перечислителя типизировано как Object) .

«коллекция» здесь кажется расплывчатой, но она точно определена на следующей странице. По сути, тип должен иметь вызов GetEnumerator (), и этот перечислитель должен (а) иметь метод MoveNext(), который возвращает логический тип, и (б) иметь свойство 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

Тип "x" в Sub Main () - Integer, поскольку свойство Current возвращает Integer.

1 голос
/ 21 февраля 2012

Либо вы должны написать:

For Each Item As SpecificType In MyCollection
....
Next

Затем он будет приводить Item к SpecificType в каждом цикле, иначе ваша коллекция должна была реализовать IEnumerable (Of T)

...