2015-01-08 4 views
0

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

В любом случае, например, когда я использую Добавить его не будет, чтобы добавить метод в класс 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 
+2

Вы не хотите, чтобы часть наследовала CollectionBase. CollectionBase - это то, что вы наследовали бы, если бы вы сами реализовывали List. Но List (Of T) уже имеет всю эту функциональность. – dwilliss

+1

Я бы либо наследовал «Collection (Of T)», либо просто реализовал List . CollectionBase немного устарел. Класс коллекции был бы чем-то другим, кроме Части. 'Part' определяет, что входит в' Parts ', который представляет собой набор частей. – Plutonix

+0

i реализовал ICollection и удалил CollectionBase и его еще не достигая объектов ... См. Мое редактирование в первом сообщении – unknown

ответ

1

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

Dim parts As New List(Of Part)() 

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

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> реализует все, что для вас.

Вы могли бы быть заинтересованы в: Guidelines for Collections

-

Для вашей части коллекции класса, чтобы быть коллекция, а затем быть оболочкой для внутренней один:

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 требует от вас написать коллекцию с нуля, но колесо уже построено.

+0

проверьте, пожалуйста, мои два класса в моем первом сообщении в разделе «Редактировать» странно – unknown

+0

кажется теперь в порядке - см. Мой блок редактирования снова для класса Parts. Я не знаю только, почему он создает для меня двойное время, например GetEnumerator1 и GetEnumerator. – unknown

+0

Я сделал два класса для списка, играющего «PartsCollection», а второй для каждого цикла: «PartEnumeration», я протестировал его и, кажется, в порядке - см. «Редактировать в мой главный пост. Как вы думаете? Я заметил, что лучше всегда отделять каждый интерфейс, который я использую, в противном случае возникли разные проблемы. Я все еще не могу понять, почему я получаю два раза: GetEnumerator() и GetEnumerator1() – unknown