ByValで受け取ったObujectの後始末

解決


す〜  2007-11-16 09:11:12  No: 138143  IP: 192.*.*.*

お世話になります

subAでselectしたダイナセットのObjectを
subB(ByVal paraObjDynaset As Object)で処理したいと考えています
subAにおけるselect時のエラーと
subBで行うテキストファイルへのPrint時のエラーを
それぞれ別に処理したいと考えProcedureを分けました

subAではsubBの処理が終わったあと
.Closeして= Nothingしてあげなくちゃならないだろうなぁ
と思っているのですが
subBでもByValで受け取ったObjectを
.Closeして= Nothingしてあげなくちゃいけないでしょうか?

ロジックで悩んでいるというより
内部動作をイメージしたと考えています
ご教示いただきたくお願いします


また
ロジック面でもこういうやり方もあるよ
などのご意見などおありでしたら
アドバイスいただければと思います
併せてよろしくお願いします

編集 削除
魔界の仮面弁士  2007-11-16 10:18:34  No: 138144  IP: 192.*.*.*

> .Closeして= Nothingしてあげなくちゃならないだろうなぁ
まぁ、oo4o の Close メソッドは、意味が無いのですけれどね。
DAO との互換性のために用意されているだけで、実際には
呼び出しても何も処理されないという。


> subBでもByValで受け取ったObjectを
> .Closeして= Nothingしてあげなくちゃいけないでしょうか?
ByVal 引数を Nothing にする必要はありません。

また、プロシージャ内の Dim 変数の場合も、プロシージャ終了時に、
自動的に Nothing されますので、Nothing 代入は必須ではありません。

ただし、プロシージャを抜ける前に、オブジェクトを早期に解放したい
場合だけは、明示的に Nothing させておいた方が良いでしょう。


> 内部動作をイメージしたと考えています
オブジェクトの「参照カウント」の概念はご存知ですか?

編集 削除
す〜  2007-11-16 11:43:39  No: 138145  IP: 192.*.*.*

>魔界の仮面弁士さん
お世話になっております
すっきりしました
ありがとうございます

明示的なコードが好きです


>オブジェクトの「参照カウント」の概念はご存知ですか?
ガベージコレクションで使う
オブジェクトのポインタ?でしょうか?
解釈間違ってましたらご指摘いただきたく
お願いいたします

VB6.0ではオブジェクトのポインタ的なモノを
意識したことがありませんでした


>また、プロシージャ内の Dim 変数の場合も、プロシージャ終了時に、
>自動的に Nothing されますので、Nothing 代入は必須ではありません。
こちらも参考になりました
ありがとうございます

編集 削除
魔界の仮面弁士  2007-11-16 14:19:33  No: 138146  IP: 192.*.*.*

>>オブジェクトの「参照カウント」の概念はご存知ですか?
>ガベージコレクションで使う
>オブジェクトのポインタ?でしょうか?

# オブジェクトのポインタだと、
#   ptr = ObjPtr(obj)
# の意味になってしまうので、微妙に違うかな…。

作成したオブジェクトを、変数等に代入すると、そのオブジェクトの
参照カウントが +1 されます。

変数の解放や Nothing の代入などによって参照が破棄されると、
参照カウントは -1 されます。

そして参照カウントが 0 になった時点で、オブジェクト自体も
破棄される…という仕組みの事ですね。


≪呼び出されたプロシージャ側で、Nothing しない場合≫
Sub Form_Load()
  Dim a As Object
  Dim b As Object

  Set a = New Collection
  '参照カウント→1になる

  Set b = a
  '参照カウント→2に増加

  Call ByValMethod(a)    '引数の参照渡し
  '参照カウント→2のまま

  Call ByRefMethod(a)    '引数の参照渡し
  '参照カウント→2のまま

  Set a = Nothing
  '参照カウント→1に減少

  Set b = Nothing
  '参照カウント→0に減少→オブジェクトが破棄される
End Sub

Sub ByValMethod(ByVal o As Object)  '値渡しのため、参照回数が増加
  '参照カウント→3に増加
End Sub  'プロシージャ終了に伴い、自動解放されて 2 に戻る

Sub ByRefMethod(ByRef o As Object)  '参照渡しのため、参照回数は変化しない
  '参照カウント→2のまま
End Sub

編集 削除
魔界の仮面弁士  2007-11-16 14:34:49  No: 138147  IP: 192.*.*.*

>> subBでもByValで受け取ったObjectを
>> .Closeして= Nothingしてあげなくちゃいけないでしょうか?
> ByVal 引数を Nothing にする必要はありません。

今度は、ByVal および ByRef それぞれで、引数を Nothing にした場合。


≪呼び出されたプロシージャ側で、Nothing する場合≫
Sub Form_Load()
  Dim a As Object
  Dim b As Object

  Set a = New Collection
  '参照カウント→1になる

  Set b = a
  '参照カウント→2に増加

  Call ByValMethodNothing(a)    '引数の参照渡し
  '参照カウント→2のまま
  'この時点で、変数 a はオブジェクトを保持したままである。

  Call ByRefMethodNothing(a)    '引数の参照渡し
  '参照カウント→1に減少 
  'ByRefMethodNothing 内の処理で、変数 a は Nothing 状態になっている。

  Set a = Nothing
  '参照カウント→1のまま
  '既に a は Nothing 状態なので、参照カウントには影響を与えない。

  Set b = Nothing
  '参照カウント→0に減少→オブジェクトが破棄される
End Sub

Sub ByValMethodNothing(ByVal o As Object)  '値渡しのため、参照回数が増加
  '参照カウント→3に増加
  Set o = Nothing
  '参照カウント→2に減少
End Sub  'すでに引数 o は Nothing なので、o が破棄されても参照カウントは変化しない

Sub ByRefMethodNothing(ByRef o As Object)  '参照渡しのため、参照回数は変化しない
  '参照カウント→2のまま
  Set o = Nothing
  '参照カウント→1に減少
End Sub  'すでに引数 o は Nothing なので、o が破棄されても参照カウントは変化しない

編集 削除
す〜  2007-11-16 17:24:42  No: 138148  IP: 192.*.*.*

>魔界の仮面弁士さん
ご丁寧な解説  ありがとうございます
大変勉強になりました

編集 削除