Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


3169 / 13644 ツリー ←次へ | 前へ→

【63774】関数の戻り値でSetを使う場合、解放するタイミング 木木木 09/12/12(土) 1:41 質問[未読]
【63775】Re:関数の戻り値でSetを使う場合、解放する... ichinose 09/12/12(土) 7:39 発言[未読]
【63776】Re:関数の戻り値でSetを使う場合、解放する... arajin 09/12/12(土) 8:29 回答[未読]
【63777】Re:関数の戻り値でSetを使う場合、解放する... ichinose 09/12/12(土) 9:33 発言[未読]
【63781】Re:関数の戻り値でSetを使う場合、解放する... 木木木 09/12/13(日) 13:58 お礼[未読]

【63774】関数の戻り値でSetを使う場合、解放する...
質問  木木木  - 09/12/12(土) 1:41 -

引用なし
パスワード
   表を取得し、その表に対してフィルタをかけたりセルの数を数えたりするマクロを組んでいます。

'表の取得
Function GetA() As Range
  Dim SttA As Range  '表の開始地点
  
  For Each SttA In Range("A1:C10")
    If SttA = "★" Then
      '取得成功
      Set GetA = Range(SttA, SttA.Offset(5, 5))
      Exit Function
    End If
  Next
  
  '失敗時
  Set GetA = Nothing
End Function

'表にフィルタをかける
Sub FilterA()
  Dim A As Range
  
  If GetA Is Nothing Then
    Exit Sub
  Else
    Set A = GetA  'Range
  End If

  '以下、フィルタをかける

  Set A = Nothing
End Sub

'表の集計を行う
Sub CntA()
  Dim A As Variant
  
  If GetA Is Nothing Then
    Exit Sub
  Else
    A = GetA    '二次元配列
  End If

  '以下、条件にあったセルの個数をカウントする
End Sub

大まかに、上記のようなコードを書きました。
GetAの戻り値をSetで設定しているのですが、表の取得成功時に、
  Set GetA = Nothing
で解放するタイミングが存在しないと思うのですが、関数の場合は解放しなくてもいいものなのでしょうか。

また、表の取得に失敗した場合に処理を中断するようにしているのですが、GetAが2回も出てきてまだるっこしく感じます。どうにか1つにまとめられないでしょうか。

以上、よろしくお願いします。

【63775】Re:関数の戻り値でSetを使う場合、解放す...
発言  ichinose  - 09/12/12(土) 7:39 -

引用なし
パスワード
   ▼木木木 さん:
おはようございます。


>大まかに、上記のようなコードを書きました。
>GetAの戻り値をSetで設定しているのですが、表の取得成功時に、
>  Set GetA = Nothing
>で解放するタイミングが存在しないと思うのですが、関数の場合は解放しなくてもいいものなのでしょうか。
GetAは、インターフェースにすぎないので不要だと思いますよ!!
(Fucntion定義のGetAに値を設定することもできませんしね)


別の例で・・・、

新規ブックにて、

クラスモジュール(Class1)に

Option Explicit
Private Sub Class_Terminate()
  Debug.Print "ok"
End Sub


標準モジュールに

Option Explicit
Sub main()
  Call geta
  MsgBox "stop"
End Sub
Function geta() As Class1
  Set geta = New Class1
End Function

このmainを実行すると、メッセージ「stop」が表示された時点で
イミディエイトウインドーには、okが表示されますよね?

この事から、データを受け取る変数がない場合は、インスタンスが
開放されている事がわかります。

Sub main2()
  Dim a As Class1
  Set a = geta
  MsgBox "stop"
  Set a = Nothing
End Sub

↑このコードとイミディエイトウインドーに okと表示されるタイミングを
比較してみてください。

【63776】Re:関数の戻り値でSetを使う場合、解放す...
回答  arajin  - 09/12/12(土) 8:29 -

引用なし
パスワード
   次に、
>また、表の取得に失敗した場合に処理を中断するようにしているのですが、
>GetAが2回も出てきてまだるっこしく感じます。
は、その通りだと思うし、GetAという関数を2度も呼びだすのは無駄ですね。
Sub FilterA()の方には、既にAという変数の用意がありますので、
Nothingであろうがなかろうが、初めに
Set A = GetA
してしまい、Nothingかの判定はAで行う方がいいでしょうね。

また、
Sub CntA()の方は、Aという変数にGetAで取得された範囲の値を
配列に取得しているようですが、ここも↑の考えにするように
別途範囲を受ける変数を用意して、一旦受けておくと良いでしょうね。
あと、余談ですが、
  A = GetA    
のところは、Set文忘れかなと一瞬思いました。
そんな勘違いを起こさないように、
  A = GetA.Value
と、Valueプロパティは略さない方が良いですね。
>If SttA = "★" とかもです。

【63777】Re:関数の戻り値でSetを使う場合、解放す...
発言  ichinose  - 09/12/12(土) 9:33 -

引用なし
パスワード
   おはようございます。

>Nothingであろうがなかろうが、初めに
>Set A = GetA
>してしまい、Nothingかの判定はAで行う方がいいでしょうね。

これは、そのとおりですね!!
こうしておけば、
set A=nothing

と明示的にオブジェクトの開放コードも書けますからね。
私もよく忘れるんですが、これを明示的に記述するコーディングポリシーを
持つべきだと思います。


そういう観点から このご質問、

>  Set GetA = Nothing
>で解放するタイミングが存在しないと思うのですが、関数の場合は解放しなくてもいい
>ものなのでしょうか。

よくこういう発想になったなあ と感心しています。

【63781】Re:関数の戻り値でSetを使う場合、解放す...
お礼  木木木  - 09/12/13(日) 13:58 -

引用なし
パスワード
   ▼ichinoseさん、arajinさん

クラスを使って解放されているかどうかを確かめるというのは
思い付かなかったので、助かりました。

また、Valueプロパティについては、今まで省略してばかりだったので
今後は気を付けたいと思います。

お答えいただきまして、ありがとうございました。

3169 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free