2012-04-21 70 views
2

すべてVB6コレクションをVB.Netに変換する

私はVB.Netに変換したい約100個のカスタムコレクションクラスを持つVB6プロジェクトを持っています。典型的な例は、次のようなものになります。アイテムが保存されている

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"ループで使用されます。文字列キーを使用したキーアクセスは非常に一般的です。インデックスによるキーアクセスは、あまり一般的ではありません。

理想的には、これらのクラスを変換するための標準的なアプローチをとってみたいと思います。私は本当に各コレクションを見直す必要はありませんし、リスト、ディクショナリなどが必要かどうかを検討するための使い方があります。これらのコレクションの中には10万個のオブジェクトが含まれているものもあれば、10個しかないものもあります。よりシンプルなオプションではより複雑な構造を使用することで、パフォーマンスの問題を引き起こしたいと考えています。

私は最善のアプローチについて助言をいただきたいと思います。私は以下を考慮した。

  1. 旧式のコレクションに固執する。したがって、VB.Netに変換するのは比較的簡単ですが、私はむしろより現代的な構造に移行したいと考えています。

  2. CAccountsはKeyedCollection(Of String、CAccount)を継承しますか。幸いにも、コレクションに保持されているクラスのほとんどはクラスの一部としてキーを持っています(例えば上記のCAccount.IdKeyなど)。これはうまくいくようです。しかし、比較的少数のクラスが数値索引によってコリレクションにアクセスします。だから、もし私が文字列キーだけでキーアクセスをしたいのであれば、おそらくこれは過剰です。

  3. 私は数値インデックスでアクセスする必要のないクラスの継承辞書(Of String、CAccount)を持っています。私がこれを持っている問題は、すべての既存の "for each"ループが "アカウントの各アカウント"に似ていることです。私はこれらの出来事をすべて「アカウント内の各アカウントごとに」変更する必要はありません。おそらく、私はデフォルトのプロパティを変更することでこれを得ることができますか?

  4. CAccountsはMyCollection(Of String、CAccount)を継承します。ここで、MyCollectionは自分専用のコレクションです。これはあまりにも苦労するようです。

オプション2に行く傾向があります。すべてをKeyedCollectionにします。次に、必要に応じて例外を設定します(非ユニークキーなど)。しかし、KeyedCollectionsがDictionaryよりもはるかに遅い場合は、DictionaryとしてDictionaryを使用し、KeyedCollectionを使用して数値インデックスでアクセスする必要があります。

すべてのアドバイスをいただければ幸いです。

+0

100個のカスタムクラスは、大きなVB6アプリケーションのようです。アップグレードする最善の方法について常に議論があります。ここでは、あなたが検討したいと思うかもしれない様々な方法のプロと詐欺について議論する最近閉鎖された質問があります:http://stackoverflow.com/questions/10252998/vb6-code-アップグレード/ 10256670#comment13187430_10256670 –

+0

このアプリのアップグレード方法について何年も考えていない場合は、数か月を費やしました。ほとんどの変換ツールを試しました。パイロットプロジェクトを実行する。私たちは無料のMicrosoftツールを使用して変換を行い、出力(集計、ADOBDからADO、古い.ocxグリッドからDatagridなど)を整理することにしました。私たちはこれが多くの仕事であることを認識しています。しかし、ビジネスロジックの多く、そしてほとんどのデータアクセスは、標準的なアプローチを持つクラス内にあります。だから我々は、グローバルなレコードコードをDataReaderなどに置き換えるコードを書いている。ゼロから始めることは現実的な選択肢ではなかった。 – djk

答えて

1
  • は、より適切と思われる方、Dictionary(Of String, Whatever)またはKeyedCollectionにすべてのコレクションを変換します。
  • プログラムを実行してパフォーマンス上の問題が発生していないか確認してください。
  • ある場合は、プロファイラを使用して原因を特定し、そのタイプをより適切なものに変更します。

しかし、私はいつもVB6コードを移植するのではなく、完全な書き換えを提案します。私の経験や、他の開発者から聞いたことがあれば、少なくとも積極的に開発されているコードでは、これは常に少ない時間で済むでしょう。コードベースが決して再び触れられない追記型ポートを持っているなら、移植はより意味をなさないかもしれませんが、現代的なコレクションの使用については心配しません。

+0

+1しかし、書き直しには非常に注意してください - 通常、部分的なポートははるかに正常です。ここで私は何をしたのですか(答えはhttp://stackoverflow.com/questions/4953725/contain-a-vb6-form-in-a-net-mdi 2番目のコメントです)、VB6アプリを実行するには3つのリリースで18ヶ月がかかりました8年間住んでいた。また、Joelはhttp://www.joelonsoftware.com/articles/fog0000000069.htmlと言っています。 ソフトウェア会社ができる最悪の戦略ミスは、コードを最初から書き直すことです。 –

+0

上記のように、我々は部分的なポートに行った。完全な書き換えが正しいアプローチであるアプリがあると確信しています。私たちの場合、ビジネスロジックの多くは、クラス内で比較的標準的なコードを使用して構築されたアルゴリズムです。これはかなりうまく移行します。非常に不器用なものがいくつかあります - これらを書き直します。私たちの目標は、最初からやったことに近いコードを得ることです。 – djk

+0

@djk公示。一貫した計画があり、あなたが話していることを知っているようです。成功のベスト。 –

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 
+0

ありがとうございます。これは先のように見える。コンストラクタNew()をインクルードする必要がありますか?私が勇気づけられたら、それぞれの衝突クラスに対してInherits List(Of CAccount)を試してから、コンパイラーが鍵付きアクセスの使用を識別しているかどうかを調べることができます。もしそうなら、私はKeyedCollectionに変更します。辞書を忘れるつもりです。既存の構文を「アカウントごとにアカウントごとに」保持できないからです。 – djk

+0

新しいコンストラクタを含めることはおそらくオプションです。 List(Of CAccount)はキー付きコレクションを提供しないため、Fin()を使用して終了します。 –

+0

私は両方の答えを正しいものとしてマークしたいと思います。また、残念ながら、新人として私はあなたの答えをupvoteするのに十分な評判を持っていません。しかし、私は助けに感謝します。ありがとう – djk

関連する問題