2

次のコードを使用したクラス「ポートフォリオ」(フィールドの1つとしてクラス「ストック」を持つ)メソッドがあります:

For i = 1 To n
    Dim TempStock As New Stock
    TempStock.Set_Stock            'sets TempStock    
    ...
Next i

「Stock」は、そのような構造、コンストラクタ、およびデストラクタを持つ私のユーザー定義クラスです。

Private StockName As String
Private CurDate As Date
Private BidPrice As Double
Private AskPrice As Double
Private StockDivs As Dictionary

Private Sub Class_Initialize()
    Set StockDivs = New Dictionary
End Sub
Private Sub Class_Terminate()
    Set StockDivs = Nothing
End Sub

すべてのループで、空のフィールドを持つ新しい一時オブジェクトを宣言して初期化することを意味しました。しかし、プログラムを段階的に実行した後、ループの最後で Class_Terminate() が呼び出されないように思えます。次のステップでは、すべてのフィールドがTempStock前のループと同じように設定されています。だから、私は次のことを理解していません:

Class_Terminate()1)で呼び出されないのはなぜNext iですか? いつ呼び出されますか?それは今正しく書かれていますか?または、オブジェクト以外のすべてのフィールドを null 値に設定するコードも作成する必要がありますか?

2) わかりました、呼び出されていませんが、まだありDim TempStock As New Stockますか? それは私に二重宣言違反を与えるべきではありませんか?またはTempStock、少なくとも新しい空のオブジェクトに設定しますか?

3) 次の違いは何ですか:

 Dim TempStock As New Stock

と:

 Dim TempStock As Stock
 Set TempStock = New Stock

それは私の問題に関係していますか?

私の問題のどの部分でも助けていただければ幸いです、ありがとう!

4

2 に答える 2

4

VBA にはブロック レベルのスコープはありません。すべての宣言 ( dim) は、それを含むプロシージャーの先頭に持ち上げられ、ルーチンの最後でのみスコープ外になります。

現在、クラスはループ内で一度インスタンス化されAs New、プロシージャが戻ったときにスコープから外れるまで終了しません。

必要な動作を得るには、次を使用する必要があります。

 Dim TempStock As Stock
 Set TempStock = New Stock

set新しいオブジェクト インスタンスを明示的に強制的に割り当てるのは であるためです。TempStock

宣言が巻き上げられると、この行Dim TempStock As New Stockは実際にはすぐに の新しいインスタンスを作成しません。むしろ、この方法でオブジェクトを作成すると、「もし私が有効な参照でない場合は、今すぐ自動作成してください」というStockタイプの変数をまたぐ呼び出しごとにスタブ コードが挿入されます。 Stock"。

于 2012-11-02T11:01:47.947 に答える
2

構文を適用する場合:

Dim TempStock As Stock
Set TempStock = New Stock

デストラクタが呼び出されます。
VBA でのオブジェクトの破棄は、参照されるオブジェクトの参照カウントがゼロ (何もない) になると発生します。
この場合、すべてのループで同じ変数「TempStock」を使用して、まったく新しい「Stock」オブジェクトをインスタンス化し、前のオブジェクトをメモリから解放します。

いずれにしてもオブジェクトは破棄されるため、このコードは不要です。

Private Sub Class_Terminate()
    Set StockDivs = Nothing
End Sub

メイン サブで明示的にStockDivsを何も設定しない場合、Class_Terminate イベントが呼び出されることに気付くでしょう。この場合、オブジェクトは、参照カウントがすでにゼロである間に別の解放メッセージを 2 回受信します (そうしないと、このイベントは発生しません)。呼ばれています)。

それにかんする:

Dim TempStock As New Stock  

Microsoft によると、両方の式は同等です:
http://msdn.microsoft.com/en-us/library/Aa903373

ただし、同等とは、それらが同一であることを意味しません。
宣言で直接 New キーワードを使用すると、実際には Stock オブジェクトもインスタンス化されますが、お気づきのように、コンストラクターは 1 回だけ呼び出され、デストラクタはループの最後でのみ呼び出されます。これは、同じオブジェクトのプロパティを再割り当てしている間 (ただし、実際には解放せずに)、各ループで同じオブジェクトを何度も使用することを暗黙的に意味します。
また、この定式化に典型的なのは、オブジェクトの初期化子が宣言時に呼び出されず、最初の使用後にのみ呼び出されるという事実です。
ほとんどのユースケースでは、両方を使用して最終的に同じ結果を得ることができます。

あなたが役に立つと思うのは、以下のコードです。コレクションに複数の株を追加したい場合 (辞書を使用することもできます) を除き、プロパティを割り当てる際に同じクラスを複数回ループする直接の理由はわかりません。

Option Explicit

Sub Stocks()

Dim oCollection         As Collection
Dim TempStock           As Stock
Dim lCnt                As Long


Set oCollection = New Collection

For lCnt = 1 To 5

    Set TempStock = New Stock

    TempStock.Set_Stock ("Stock_" & lCnt)       'sets TempStock name eg. 
    oCollection.Add TempStock
Next lCnt

End Sub

コレクションに複数の株式を追加する場所。

于 2012-11-02T11:17:16.870 に答える