2

全部,

我有一个 VB6 项目,其中包含大约 100 个自定义集合类,我想将其转换为 VB.Net。一个典型的例子是这样的。

Class CAccounts
     Private m_Accounts As New Collection

     Public Sub Add(newItem As CAccount)
         m_Accounts.Add newItem, newItem.IdKey
     End Sub
     Public Sub Remove(index As Variant)
         m_Accounts.Remove index
     End Sub
     Public Function Item(index As Variant) As CAccount
         Set Item = Nothing
         On Error Resume Next
         Set Item = m_Accounts.Item(index)
     End Function

     .........

存放物品的位置

Class CAccount
    Public Id as long
    Public Code as String
    Public Name as string
    Public Sub Init(ByVal Id as Long)
        Me.Id = Id
        Code = ""
        Name = ""
    End Sub
    Public Property Get IdKey() as String
        IdKey = Code
    End Property

    ......

项目中的所有集合类都使用这种标准方法。但是,并非集合类的所有属性/方法都被实际使用。大多数集合用于“for each”循环。使用字符串键的键控访问非常普遍。按索引进行键控访问要少得多。

理想情况下,我想采用标准方法来转换这些类。我真的不想检查每个集合,它的用途是考虑我是否需要一个列表、字典等。其中一些集合包含 100,000 个对象,有些只包含 10 个。但是,另一方面我不不想通过使用更复杂的结构而导致性能问题,而使用更简单的选项。

我将不胜感激有关最佳方法的任何建议。我考虑了以下几点。

  1. 坚持旧式收藏。因此,转换为 VB.Net 会相对容易,但是,我宁愿转向更现代的结构。

  2. 让 CAccounts 继承 KeyedCollection(Of String, CAccount)。幸运的是,集合中的大多数类都将密钥作为类的一部分(例如上面的 CAccount.IdKey)。这似乎运作良好。但是,相对较少的类将通过数字索引访问该集合。那么,如果我只想通过字符串键进行键控访问,这可能是矫枉过正吗?

  3. 让 CAccounts Inherit Dictionary(Of String, CAccount) 用于我不需要通过数字索引访问的类。我遇到的问题是所有现有的“for each”循环就像“for each account in accounts”。我不想将所有这些发生更改为“针对accounts.Values 中的每个帐户”之类的东西。虽然也许我可以通过更改默认属性来解决这个问题?

  4. 让 CAccounts 继承 MyCollection(Of String, CAccount),其中 MyCollection 是我自己的定制集合。这似乎有点太辛苦了。

我倾向于选择选项 2 - 将所有内容都设为 KeyedCollection。然后在需要时进行例外处理(例如非唯一键)。但是,如果 KeyedCollection 比 Dictionary 慢得多,我可能会选择 Dictionary 作为标准,并且只需在需要通过数字索引访问的地方使用 KeyedCollection。

所有建议表示赞赏。

4

2 回答 2

1
  • 将所有集合转换为Dictionary(Of String, Whatever)KeyedCollection,以更合适的为准。
  • 通过运行程序查看是否存在性能问题。
  • 如果有,请使用分析器查明罪魁祸首并将其类型更改为更合适的类型。

但总的来说,我总是建议完全重写而不是尝试移植 VB6 代码。根据我的经验,以及从其他开发人员那里听到的情况,这总是会消耗更少的时间,至少对于正在积极开发的代码而言。如果您有一个永远不会再次触及代码库的一次性写入端口,那么移植可能更有意义,但我不必担心使用现代集合,只需使用兼容性类即可。

于 2012-04-21T12:50:53.427 回答
0

你会想要一篇KeyedCollection<TKey, TItem> MSDN 文章:http: //msdn.microsoft.com/en-us/library/ms132438.aspx

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

' This class represents a very simple keyed list of OrderItems,
' inheriting most of its behavior from the KeyedCollection and 
' Collection classes. The immediate base class is the constructed
' type KeyedCollection(Of Integer, OrderItem). When you inherit
' from KeyedCollection, the second generic type argument is the 
' type that you want to store in the collection -- in this case
' OrderItem. The first generic argument is the type that you want
' to use as a key. Its values must be calculated from OrderItem; 
' in this case it is the Integer field PartNumber, so SimpleOrder
' inherits KeyedCollection(Of Integer, OrderItem).
'
Public Class SimpleOrder
    Inherits KeyedCollection(Of Integer, OrderItem)

    ' The parameterless constructor of the base class creates a 
    ' KeyedCollection with an internal dictionary. For this code 
    ' example, no other constructors are exposed.
    '
    Public Sub New()
        MyBase.New()
    End Sub

    ' This is the only method that absolutely must be overridden,
    ' because without it the KeyedCollection cannot extract the
    ' keys from the items. The input parameter type is the 
    ' second generic type argument, in this case OrderItem, and 
    ' the return value type is the first generic type argument,
    ' in this case Integer.
    '
    Protected Overrides Function GetKeyForItem( _
        ByVal item As OrderItem) As Integer

        ' In this example, the key is the part number.
        Return item.PartNumber   
    End Function

End Class
于 2012-04-21T12:50:24.920 回答