[英]Is it possible to automatically handle List.Contains by comparing a property on the item?
[英]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.