- PR -

Dispose()の使い方

投稿者投稿内容
きたさん
常連さん
会議室デビュー日: 2003/09/11
投稿数: 26
投稿日時: 2004-03-27 17:39
久しぶりに投稿します。
宜しくお願いします。

現在C#を使ってWindowsアプリの開発をしています。
そこで質問なのですが、Dispose()を使用してもクラス(インスタンス)が破棄されずに困っています。使い方間違ってますでしょうか?

//クラス
public class test:IDisposable
{
public void Dispose();
{}

public void func()
{
処理
}
}

//クライアント
private void button1_Click(object sender, System.EventArgs e)
{
test testObj= new test();
testObj.Dispose();//インスタンスの破棄
testObj.func()//←破棄された後なのでエラーになるはず
}

上のようにDispose()処理をいれてもエラーがでずに、正常に動きます。
やっぱりDispose()の使い方を解ってないんでしょうかね。。。

ご指導宜しくお願いします。
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2004-03-27 18:34
Dispose()というのは別にメモリからオブジェクトを消したりしてくれるわけではなくて、終了処理(開いているファイルを閉じるとか)をするためのメソッドだと思います。

なので、何もしなければ何も起きないかと。
きたさん
常連さん
会議室デビュー日: 2003/09/11
投稿数: 26
投稿日時: 2004-03-27 18:48
ご返答ありがとうございます。

ではGCによるメモリ破棄ではなくて、プログラム上でクラス(インスタンス)を破棄するような方法はどのように実装すればいいのでしょうか?
TER
会議室デビュー日: 2003/04/15
投稿数: 5
お住まい・勤務地: 大阪
投稿日時: 2004-03-27 20:18
インスタンスを破棄するという意味がいまいちわかりませんが、エラーを出したいのであれば、nullを参照すればいいのでは?

test testObj= new test();
testObj.Dispose();//インスタンスの破棄
testObj = null;
testObj.func()//←参照が外された後なのでエラーになるはず



[ メッセージ編集済み 編集者: TER 編集日時 2004-03-27 20:29 ]
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2004-03-27 22:51
「インスタンスを破棄する」というのはC++のdeleteのようなイメージでしょうか?

そういったメモリの管理をプログラマが意識しなくて良いように.NETフレームワークに管理され(managed)たプログラムを作っているわけですが、もしメモリ上からなくしたい場合は・・・
あるメソッド内でnewし、その中でしか使わないようなものであればTERさんのおっしゃるようにnullで参照をはずしてGC.Collect()を実行するとメモリ上からなくなるかもしれません
おそらくメモリ上からなくなるとは思いますが確認はできないのでなんとも・・・
複数の場所から参照されていて、そのオブジェクトが仕事をするのをやめて欲しいのであれば、そういう機能を実装してみてはどうでしょうか。
Dispose()が呼び出されたら、それ以降どんなメソッドを呼ばれてもExceptionを投げるようにするとか。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-27 23:48
unibon です。こんにちわ。

引用:

きたさんさんの書き込み (2004-03-27 18:48) より:
ではGCによるメモリ破棄ではなくて、プログラム上でクラス(インスタンス)を破棄するような方法はどのように実装すればいいのでしょうか?


.NET はほとんど知らないのですが、Java と同じだろうという仮定のもと、書きます。
インスタンスを破棄する方法を探すのではなく、アプリケーションの側でインスタンスを破棄することはできないという前提で、アプリケーションをコーディングするべきだろうと思います。アプリケーションプログラマーができることにはつぎのものがあります。

(1) インスタンスが不要になったら、そのインスタンスをいずれの変数からも参照しなくする。
(2) インスタンスが破棄されるタイミングで呼ばれるコールバックメソッドに、後始末の処理を書く。このコールバックはガーベッジコレクタによって任意のタイミングでおこなわれる。なお、こうやって呼ばれるためには(1)のようにすることが必要。
(3) すぐに破棄したい場合は、Dispose や Close といった、「解放する・閉じる」ためのメソッドを用意しておき、自分のコードから明示的に呼ぶという決まりごとにする。ただ、これもこのメソッドを持つインスタンスそのものを破棄できるわけではなく、このインスタンスが集約しているインスタンスを破棄するだけ。これも実際は破棄するというのは正しくなく、これもやっぱり集約しているインスタンスに対して Dispose/Close を呼ぶだけのことしかできない。

すなわち、破棄は明示的におこなえません。破棄のタイミングも制御できません。
#デバッグ的な API を呼べばできるのかもしれませんが、普通のコードからは使いません。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-03-27 23:55
別に何らかの資源(これは、単に不要になったメモリとかではなく、明示的に開放する必要のあるリソース、例えばIDisposableな他のクラス等)を持っていないクラスでは、IDisposableを実装する必要はありません。というか、何かを破棄する必要はありません。
# 単に確保しているだけのメモリ以外の、何かを開放する必要があるときに使う物です。

それと、IDisposableを実装したところで、それ自身がインスタンス開放のための何かの機能を持つわけではありません。単に、破棄するという意味の共通のインターフェイスをサポートするだけの物で、破棄処理自体は自分で書きます。
もう使えない事を明示する必要があるのなら、Disposeされた後はObjectDisposedExceptionでも投げるようにしとけばいいと思いますが、他に資源がないのならわざわざそれを実装する必要はない事が多いです。

オブジェクトは、どこからも参照されなくなった(表現が少し微妙ですが)時点で、次回のGC発動でメモリから開放されます。それまではメモリに残り続けるわけですが、普通気にする必要はありません(必要に応じてGCが動くため)。これを開放するにはGCを自分で発動させるしかないでしょうが、それには余り意味はありません。むしろ弊害となる可能性の方が高いです。
きたさん
常連さん
会議室デビュー日: 2003/09/11
投稿数: 26
投稿日時: 2004-03-28 01:23
みなさんご返答ありがとうございます。返答が遅くなって申し訳ありません。

結局今回何がしたかったというと、

データクラス(配列の階層を持つクラス)を作成し、
その配列クラスの要素を動的に変化させたかったんです。
その時、要素を増やす分には問題ないのですが、減らす時(破棄)をどうすればいいのかがわからなかったので投稿させていただきました。

例えば、
//Testクラス
public class Test
{}

//Testの配列クラス
public class TestList
{
private Test[] ArrayTest;
}


つまり、一旦クラスをGCによる開放ではなく、明示的に開放し、その後に再度インスタンスを作成する(データクラスのリフレッシュといるイメージかな?)ことで今回の問題を解決しようと考えていました。


だらだらとわかりにくい説明になってしまいましたが、ご意見よろしくお願いいたします。

スキルアップ/キャリアアップ(JOB@IT)