在VB6中,曾经有一个Collection数据类型,它允许通过其键或序号检索集合中的项目。但是,它没有强类型。
现在,使用VB.Net,我正在寻找一个强类型的合适替代品,可以与泛型集合一起使用。
这是我想要做的一个简单的例子。唯一的问题是底层集合类BindingList不支持通过alpha键有效地检索项目,因此我必须循环遍历元素以获取我正在寻找的项目。对于大型馆藏,这效率不高。
我查看了各种Collection类型,但没有找到合适的替代品。
这是我想要做的,除了使用Item属性完成的循环。
如果可以的话,请不要只是说“使用哈希表”或类似的内容,请详细说明我在下面的简短示例中所做的详细说明。
Public Class Car
Public Sub New(ByVal keyName As String, ByVal property1 As String)
_KeyName = keyName
_Property1 = property1
End Sub
Dim _KeyName As String
Public Property KeyName() As String
Get
Return _KeyName
End Get
Set(ByVal value As String)
_KeyName = value
End Set
End Property
Public _Property1 As String
Public Property Property1() As String
Get
Return _Property1
End Get
Set(ByVal value As String)
_Property1 = value
End Set
End Property
End Class
Public Class Cars
Inherits System.ComponentModel.BindingList(Of Car)
Public Overloads ReadOnly Property Item(ByVal key As String) As Car
Get
For Each CurrentCar As Car In Me.Items
If CurrentCar.KeyName = key Then
Return CurrentCar
End If
Next
Return Nothing
End Get
End Property
End Class
答案 0 :(得分:4)
我相信你正在寻找Dictionary<TKey, TValue>
。实际上,如果您确实希望自己的集合类具有强类型且不是(本身)通用的,那么如果将父类更改为Dictionary<string, Car>
,则应该全部设置。当然,这一切都假设您使用显式字符串键将汽车添加到集合中。如果您希望查找基于集合中属性的值,那么您最好使用或继承List<Car>
并使用LINQ查询列表。然后你可以......
Public Overloads ReadOnly Property Item(ByVal key As String) As Car
Get
Return (from c in Me where c.KeyName = key select c).SingleOrDefault()
End Get
End Property
答案 1 :(得分:0)
你真的需要通过密钥AND索引进行访问吗?
如果不这样做,则使用Dictionary(Of String,Car),然后使用
- MyCol.Items("XXX")
按键检索项目(或简写MyCol(“XXX”))
- MyCol.ContainsKey("XXX")
来测试集合中是否存在密钥
- 如果要枚举所有对象及其键,请在MyCol中For Each Entry as KeyValuePair(Of String, Car)
- 对于MyCol.Values中的每个条目作为Car,如果要在不考虑密钥的情况下枚举条目
如果您需要通过索引和密钥进行访问,我担心最好的办法是使用List(of Car)和Dictionary(of Car)滚动到一个自定义集合类中,因为我相信它们离开了那种对大多数问题都没有用的收藏品。
答案 2 :(得分:0)
我认为这是我最好的解决方案。我欢迎评论更好的方式!
Imports Microsoft.VisualBasic
Public Class Car
Implements Xs(Of Car).IKeyName
Private _KeyName As String
Public Sub New(ByVal keyName As String, ByVal property1 As String)
_KeyName = keyName
_Property1 = property1
End Sub
Public Property KeyName() As String Implements Xs(Of Car).IKeyName.KeyName
Get
Return _KeyName
End Get
Set(ByVal value As String)
_KeyName = value
End Set
End Property
Public _Property1 As String
Public Property Property1() As String
Get
Return _Property1
End Get
Set(ByVal value As String)
_Property1 = value
End Set
End Property
End Class
Public Class Cars
Inherits System.ComponentModel.BindingList(Of Car)
Public Overloads ReadOnly Property Item(ByVal key As String) As Car
Get
For Each CurrentCar As Car In Me.Items
If CurrentCar.KeyName = key Then
Return CurrentCar
End If
Next
Return Nothing
End Get
End Property
End Class
Public Class X
Private _KeyName As String
Public Property KeyName() As String
Get
Return _Keyname
End Get
Set(ByVal value As String)
_Keyname = value
End Set
End Property
End Class
Public Class Xs(Of X)
Inherits Hashtable
Interface IKeyName
Property KeyName() As String
End Interface
Public Shadows Sub Add(ByVal item As IKeyName)
MyBase.Add(item.KeyName, item)
End Sub
Public Shadows ReadOnly Property Item(ByVal key As String) As x
Get
If Me.ContainsKey(key) Then
Return MyBase.Item(key)
Else
'If I mispell a key, I don't want to end up creating a new mispelled version, I want an error
Throw New Exception("Element with key " & key & " is not found")
End If
End Get
End Property
End Class
Public Class Cars2
Inherits Xs(Of Car)
End Class
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim MyCar As New Car("key1", "prop1")
'First approach
Dim MyCars As New Cars
MyCars.Add(MyCar)
Dim RetrievedCar As Car = MyCars.Item("key1") 'Inefficient retrieval by key (uses looping)
'Second approach
Dim Cars2 As New Cars2
Cars2.Add(MyCar)
Dim RetrievedCar2 As Car = Cars2.Item("key1") 'Can now efficiently retreive an item by its key
End Sub
答案 3 :(得分:0)
如果您需要,可以通过索引和按键访问System.Collections.Specialized命名空间中的OrderedDictionary。但是看看你的解决方案,它看起来像一个标准的字典,但效率较低,因为它强制键的字符串类型。
有什么理由你不能使用Dictionary .NET提供给你的,或者像在OrderedDictionary中那样已经在.NET中的其他集合类型?