繁体   English   中英

如何使用item的属性实现/覆盖自定义Collection类的Protected List.Contains()

[英]How to implement/override Protected List.Contains() for a custom Collection Class using a property of item

我不完全确定上面标题的措词是否正确。 我想最简单的解释方法是将代码放在下面以供参考,然后给出我希望的行为。


Public Class Domino
    Public ReadOnly MinimumSideValue As Integer = 0
    Public ReadOnly MaximumSideValue As Integer = 6

    Public Property key As Integer
    Public Property Side1 As Integer
    Public Property Side2 As Integer

    Public Sub New(side1Value As Integer, side2Value As Integer)
        Me.Side1 = side1Value
        Me.Side2 = side2Value
        ' Key should be a two digit number. side values 5 and 1 -> 51
        Me.key = Integer.Parse(Side1.ToString & Side2.ToString)
    End Sub

    Public Overrides Function ToString() As String
        Return Convert.ToString(Me.key)
    End Function

End Class

Public Class DominoCollection
    Inherits System.Collections.CollectionBase

    Public Sub AddDomino(newDomino As Domino)
        ' Not sure if I should be calling Contains on the Protected List object
        If Not List.Contains(newDomino) Then
            List.Add(newDomino)
        End If    
    End Sub

    Public Function Contains(objDomino as Domino) As Boolean
        ' Need to check if a domino that has the same key already exists
        Dim found As Boolean = False
        For i = 0 To List.Count - 1 'This will fail if the list is empty...
            If DirectCast(List.Item(i), Domino).key = objDomino.key Then found = True
        Next
        Return found
    End Function    

End Class

第一代码列表是将创建多个实例的类。 第二类是将包含第一类实例的集合。 集合中不应包含重复的项目。 因此,当我从CollectionBase调用内置受保护的List对象上的contains方法时,我希望它在第一类的key属性中搜索具有相同值的重复项的项目列表。

我不确定是否可以覆盖List.Contains方法,因为它是受保护的对象,并且/或者我是否应该真正创建自己的contains方法。 我尝试创建自己的.Contains方法,但是如果列表为空,它将失败。


编辑

我知道我的代码不在C#中。 但是,由于它是.NET,因此C#答案将与VB一样有帮助。


编辑:修改后的代码

在看到下面的一些解决方案后,我得到了以下内容,到目前为止,它看起来像我想要的那样可以工作。 但是,我不确定我是否正确实现了Item属性。 到目前为止,我尚未对其进行测试,因为我无法在应用程序的其余部分中使用它,我只是在尝试降低框架。

Friend Class DominoCollection
    Private domCol As Dictionary(Of Integer, Domino)

    Public ReadOnly Property Keys As System.Collections.Generic.Dictionary(Of Integer, Domino).KeyCollection
        Get
            Return domCol.Keys
        End Get
    End Property

    Public ReadOnly Property Values As System.Collections.Generic.Dictionary(Of Integer, Domino).ValueCollection
        Get
            Return domCol.Values
        End Get
    End Property

    Default Public Property Item(DominoKey As Integer) As Domino
        Get
            If domCol.ContainsKey(DominoKey) Then
                Return domCol.Item(DominoKey)
            Else
                Throw New KeyNotFoundException(String.Format("Cannot find key {0} in internal collection"))
            End If
        End Get
        Set(value As Domino)
            If domCol.ContainsKey(DominoKey) Then
                domCol.Item(DominoKey) = value
            Else
                Throw New KeyNotFoundException(String.Format("Cannot find key {0} in internal collection"))
            End If
        End Set
    End Property

    Default Public Property Item(domino As Domino) As Domino
        Get
            If domCol.ContainsKey(domino.key) Then
                Return domCol.Item(domino.key)
            Else
                Throw New KeyNotFoundException(String.Format("Cannot find key {0} in internal collection"))
            End If
        End Get
        Set(value As Domino)
            If domCol.ContainsKey(domino.key) Then
                domCol.Item(domino.key) = value
            Else
                Throw New KeyNotFoundException(String.Format("Cannot find key {0} in internal collection"))
            End If
        End Set
    End Property

    Public Sub New()
        domCol = New Dictionary(Of Integer, Domino)
    End Sub

    Public Sub Add(dom As Domino)
        If Not domCol.ContainsKey(dom.key) Then
            domCol.Add(dom.key, dom)
        End If
    End Sub

    Public Function Contains(dom As Domino) As Boolean
        Return domCol.ContainsKey(dom.key)
    End Function

    ' flexibility:
    Public Function Remove(dom As Domino) As Boolean
        If domCol.ContainsKey(dom.key) Then
            domCol.Remove(dom.key)
            Return True
        Else
            Return False
        End If
    End Function

    Public Function Remove(key As Integer) As Boolean
        If domCol.ContainsKey(key) Then
            domCol.Remove(key)
            Return True
        Else
            Return False
        End If
    End Function

    Public Function Count() As Integer
        Return domCol.Count
    End Function

    Public Sub Clear()
        domCol.Clear()
    End Sub

End Class

是的,您绝对应该从通用集合类继承或实现通用集合接口。

我不确定VB的确切语法,但我想代替List.Contains要使用带有lambda的Linq扩展Any 我认为它是这样的:

List.Any(Function(d as Domino) d.key = newDomino.key)

如果List中的任何元素与键匹配,则将返回true。

考虑到Domino.Key的核心重要性,我认为使用Dictionary的类将使事情变得最简单。 由于您的代码总是在寻找决定是否存在Domino对象等的内容,因此Dictionary将有助于检测并防止重复等。

Friend Class DominoCollection
    Private mcol As Dictionary(Of Integer, Domino)

    Public Sub New()
        mcol = New Dictionary(Of Integer, Domino)
    End Sub

    Public Sub Add(dom As Domino)
        If mcol.ContainsKey(dom.key) = False Then
            mcol.Add(dom.key, dom)

        ' optional: replace - dont know if this is needed
        Else
            mcol(dom.key) = dom
        End If
    End Sub

    Public Function Contains(dom As Domino) As Boolean
        Return mcol.ContainsKey(dom.key)
    End Function

    ' flexibility:
    Public Function Remove(dom As Domino) As Boolean
        If mcol.ContainsKey(dom.key) Then
            mcol.Remove(dom.key)
            Return True
        End If
        Return False
    End Function

    Public Function Remove(key As Integer) As Boolean
        If mcol.ContainsKey(key) Then
            mcol.Remove(key)
            Return True
        End If
        Return False
    End Function

End Class

对于一个或多个项目:

Public Function Item(key As Integer) As Domino
    Return mcol(key)
End Function

Public Function Items() As List(Of Domino)
    Return New List(Of Domino)(mcol.Values)
End Function

Items隐藏了通常需要迭代的KeyValuePair ,并允许您对集合执行一个简单的For / Each循环(需要):

Dim doms As New DominoCollection

doms.Add(New Domino(1, 2))
doms.Add(New Domino(2, 3))
doms.Add(New Domino(4, 6))

For Each d As Domino In doms.Items
    Console.WriteLine("s1:{0} s2:{1} k:{2}", d.Side1, d.Side2, d.key.ToString)
Next

输出量

s1:1 s2:2 k:12
s1:2 s2:3 k:23
s1:4 s2:6 k:46

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM