Это не собирается CollectionBase, Enumerator,Enumerable объектов

У меня есть класс в коде ниже, где помимо равно и методы хеша из IEqualityComparer, который я использую, я также хочу реализовать add, remove, item, count from list а также GetEnumerator (current,movenext,position), Поэтому я решил использовать Inherits CollectionBase, IEnumerator и IEnumerable.

Во всяком случае, например, когда я использую Add, он не собирается в метод Add в классе Part, или когда я делаю для каждого, он не собирается GetEnumerator переходить дальше. В чем проблема?

Это класс:

Imports System.Collections.Generic

Public Class Part
    Inherits CollectionBase
    Implements IEqualityComparer(Of Part), IEnumerator(Of Part), IEnumerable(Of Part)

    Private _values As List(Of Part)
    Private _currentIndex As Integer

    Public Property _comparisonType As EqualsComparmission

    Public Sub New(ComparisonType As EqualsComparmission)
        Me._comparisonType = ComparisonType
    End Sub

    Public Sub New(values As List(Of Part))
        _values = New List(Of Part)(values)
        Reset()
    End Sub

    Public Sub New()
    End Sub

    Public Property PartName() As String

    Public Property PartId() As Integer


    Public Overrides Function ToString() As String
        Return "ID: " & PartId & "   Name: " & PartName
    End Function


    Public Sub Add(ByVal value As Part)
        Me.List.Add(value)
    End Sub

    Public Sub Remove(ByVal Index As Integer)
        If Index >= 0 And Index < Count Then
            List.Remove(Index)
        End If
    End Sub

    Public ReadOnly Property Item(ByVal Index As Integer) As Part
        Get
            Return CType(List.Item(Index), Part)
        End Get
    End Property

    Public ReadOnly Property Current() As Part
        Get
            Return _values(_currentIndex)
        End Get
    End Property

    Public ReadOnly Property Current1 As Object Implements IEnumerator.Current
        Get
            Return Current
        End Get
    End Property

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        _currentIndex += 1
        Return _currentIndex < _values.Count
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        _currentIndex = -1
    End Sub

#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
    'Protected Overrides Sub Finalize()
    '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

    Public Function GetEnumerator1() As IEnumerator(Of Part) Implements IEnumerable(Of Part).GetEnumerator
        Return CType(Me, IEnumerator)
    End Function

    Public ReadOnly Property Current2 As Part Implements IEnumerator(Of Part).Current
        Get
            Return Current
        End Get
    End Property

    Public Function Equals1(x As Part, y As Part) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Part).Equals
        If x Is Nothing AndAlso y Is Nothing Then Return True
        If x Is Nothing OrElse y Is Nothing Then Return False

        Select Case _comparisonType
            Case EqualsComparmission.PartId
                Return x.PartId = y.PartId
            Case EqualsComparmission.PartName
                Return String.Equals(x.PartName, y.PartName)
            Case EqualsComparmission.PartId_and_PartName
                Return x.PartId = y.PartId AndAlso String.Equals(x.PartName, y.PartName)
            Case Else
                Throw New NotSupportedException("Unknown comparison type for parts: " & _comparisonType.ToString())
        End Select
    End Function

    Public Function GetHashCode1(obj As Part) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Part).GetHashCode
        Select Case _comparisonType
            Case EqualsComparmission.PartId
                Return obj.PartId
            Case EqualsComparmission.PartName
                Return If(obj.PartName Is Nothing, 0, obj.PartName.GetHashCode())
            Case EqualsComparmission.PartId_and_PartName
                Dim hash = 17

                hash = hash * 23 + obj.PartId
                hash = hash * 23 + If(obj.PartName Is Nothing, 0, obj.PartName.GetHashCode())
                Return hash
            Case Else
                Throw New NotSupportedException("Unknown comparison type for parts: " & _comparisonType.ToString())
        End Select
    End Function

End Class

и это тестовый код:

Dim parts As New List(Of Part)()

   parts.Add(New Part() With { _
           .PartName = "ala", _
           .PartId = 11 _
      })
        parts.Add(New Part() With { _
             .PartName = "shift lever", _
             .PartId = 1634 _
        })

   For Each aPart As Part In parts
            Console.WriteLine(aPart)
        Next

Отредактировано:

PartsCollection, которая реализует ICollection для операций со списком:

Public Class PartsCollection
    Implements ICollection(Of Part)

    ' Enumerators are positioned before the first element 
    ' until the first MoveNext() call. 
    Dim position As Integer = -1

    Private myList As List(Of Part)

    Public Sub New()

        If myList Is Nothing Then
            myList = New List(Of Part)
        End If

    End Sub

    Public Sub Add(item As Part) Implements ICollection(Of Part).Add
        myList.Add(item)
    End Sub

    Public Sub Clear() Implements ICollection(Of Part).Clear

    End Sub

    Public Function Contains1(item As Part) As Boolean Implements ICollection(Of Part).Contains
        Return myList.Contains(item)
    End Function

    Public Sub CopyTo(array() As Part, arrayIndex As Integer) Implements ICollection(Of Part).CopyTo

    End Sub

    Public Function GetEnumerator() As IEnumerator(Of Part) Implements IEnumerable(Of Part).GetEnumerator
        Return New PartsEnumeration(myList)
    End Function



    Public ReadOnly Property Count As Integer Implements ICollection(Of Part).Count
        Get

        End Get
    End Property

    Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of Part).IsReadOnly
        Get

        End Get
    End Property

    Public Function Remove(item As Part) As Boolean Implements ICollection(Of Part).Remove

    End Function

    Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator

    End Function
End Class

PartsEnumeration для каждого цикла:

Public Class PartsEnumeration
    Implements IEnumerator(Of Part)

    Private mmyList As List(Of Part)
    Dim position As Integer = -1

    Public Sub New(ByVal myList As List(Of Part))
        mmyList = myList
    End Sub

    Public ReadOnly Property Current As Part Implements IEnumerator(Of Part).Current
        Get
            Try
                Return mmyList(position)
            Catch ex As IndexOutOfRangeException
                Throw New InvalidOperationException()
            End Try
        End Get
    End Property


    Public ReadOnly Property Current1 As Object Implements IEnumerator.Current
        Get
            Try
                Return mmyList(position)
            Catch ex As IndexOutOfRangeException
                Throw New InvalidOperationException()
            End Try
        End Get
    End Property

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        If position < mmyList.Count - 1 Then
            position += 1
            Return True
        End If
        Return False
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        position = -1
    End Sub

#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
    'Protected Overrides Sub Finalize()
    '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class

Тестовый код:

 Dim cos As New Part With { _
             .PartName = "crank arm", _
             .PartId = 1234 _
        }

        Dim cos3 As New Part With { _
          .PartName = "cranddk arm", _
          .PartId = 123334 _
     }

        myParts.Add(something1)
        myParts.Add(something2)

        Dim p As Boolean = myParts.Contains1(something1)
        Console.WriteLine(p)

        For Each ii In myParts
            Console.WriteLine(ii.ToString)
        Next

1 ответ

Решение

Вы склеиваете две вещи, которые связаны, но не одно и то же, и составляете список коллекций.

Dim parts As New List(Of Part)()

Поскольку Part наследуется от CollectionBase, вы создаете список коллекций. Класс Collection должен использоваться для реализации методов управления списком / коллекцией, таких как функциональность Extension в другом вопросе. Он будет управлять списком для вас.

Class Part
    Property Name As String
    Property ID As Integer
End Class

Class Parts
    Private myList As New List(Of Part)

    Public Sub Add(item As Part)

    Public Function IndexOfPartName...

    etc

    Public Sub Remove(item As Part)

    ' some might just be wrappers:
    Public Function Contains(p As Part) As Boolean
        Return myList.Contains(Part)
    End Function

End Class

Код, который потребляет это:

Friend myParts As New Parts

myParts.Add(New Part(...))

Dim p As Part = myParts.IndexOfPartName("screws")

После того, как вы выработаете необходимую вам функциональность и то, как она будет использоваться, вы можете изменить ее на Inherit Collection<T> так что вы можете сделать For Each p As Part in Parts, Но работайте над получением жизнеспособного класса коллекции, прежде чем приступать к интерфейсам и тому подобному. Некоторые из них могут не понадобиться, так как Collection<T> реализует все это для вас.

Вы можете быть заинтересованы в: Руководство для коллекций

-

Чтобы ваш класс коллекции частей был коллекцией, а не оболочкой для внутреннего:

Imports System.ComponentModel
Class Parts
    Inherits Collection(Of Part)

    ' ALREADY implemeted for you are:
    ' Contains, Count, Add, Clear, IndexOf, Insert, EQUALS
    ' Item, Items, Remove, RemoveAt and RemoveItem

Таким образом, все, что вам нужно сделать, это переопределить те методы, которые делают что-то иначе, чем вы хотели бы, или расширить функциональность, такую ​​как IndexOfPartName,

ICollection требует от вас написать коллекцию с нуля, но колесо уже построено.

Другие вопросы по тегам