- PR -

Dispose()の使い方

投稿者投稿内容
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-03-28 01:52
諸農です。

引用:

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



必要なものだけArray.Copy()するのはダメですか?


_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
TER
会議室デビュー日: 2003/04/15
投稿数: 5
お住まい・勤務地: 大阪
投稿日時: 2004-03-28 04:24
ArrayListではだめですか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-28 08:07
引用:

なちゃさんの書き込み (2004-03-27 23:55) より:
別に何らかの資源(これは、単に不要になったメモリとかではなく、明示的に開放する必要のあるリソース、例えばIDisposableな他のクラス等)を持っていないクラスでは、IDisposableを実装する必要はありません。というか、何かを破棄する必要はありません。
# 単に確保しているだけのメモリ以外の、何かを開放する必要があるときに使う物です。


 う〜ん、その説明ではわかりにくいかも。

 ここで「資源」は「アンマネージドリソース」です。メモリも、newで確保した分は“マネージドリソース”なので、Dispose不要です。が、Win32API呼び出しを利用して、GlobalAllocateなどをした場合は、“アンマネージドメモリ”になるので、Diposeできるようにすることが必要です。

 Disposeについては、MSDN上にガイドラインがあります。
「アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装」にありますので、ご参照を。なお、IDisposableを実装するクラスでは、デストラクタを明示的に実装して、クラスのインスタンスが破棄されるときに確実にアンマネージドメモリを解放するようにしなければなりません。
iStation
大ベテラン
会議室デビュー日: 2003/12/08
投稿数: 158
投稿日時: 2004-03-28 08:20
こんな感じ...?

~Test()
{
Console.WriteLine("finalizing Heap Used:{0}", GC.GetTotalMemory(true));
Dispose();
}

public void Dispose()
{ // for Resource Release
Console.WriteLine("disposing Heap Used:{0}", GC.GetTotalMemory(true));
GC.SuppressFinalize(this);
}
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2004-03-28 08:37
引用:

きたさんさんの書き込み (2004-03-28 01:23) より:
要素を増やす分には問題ないのですが、・・・


というのはどういう風に実装しているんでしょうか。
減らすのも同じ実装でかまわないと思うのですが。

前にも書きましたが、.NETではメモリの管理をプログラマが意識しなくて良いようになっていますので、減らす時(破棄)はその減らしたい部分の要素をどこからも参照しないようにすれば勝手に消えます。

コード:
private test[] ArrayTest;

public int ArrayTestLength
{
	get
	{
		return ArrayTest.Length;
	}
	set
	{
		test[] tempArray=new test[value-1];	//長さ変更後の配列
		int copyLength;				//コピーする要素の数

		//コピーする要素の数を決定する
		if(ArrayTest.Length < tempArray.Length)
		{
			copyLength=ArrayTest.Length;
		}
		else
		{
			copyLength=tempArray.Length;
		}

		//要素のコピー
		Array.Copy(ArrayTest,tempArray,copyLength);

		this.ArrayTest=tempArray;
	}
}


ちょっと書いてみただけなので動くかどうか分かりませんが、「要素を増やす」というのはこんな感じで実装しているんですよね。(VB.NETにはReDimとかいう機能があるみたいですけど)
増やすときには元の要素を全てコピーするわけですが、減らすときには新しい配列の長さ分だけコピーしてあぶれた分の要素は参照しなくするという違いがあるだけで、結局増やすも減らすも同じことだと思うんですけど。
何度も書きますが、明示的に開放なんてしなくても勝手に消えてくれますので。
きたさん
常連さん
会議室デビュー日: 2003/09/11
投稿数: 26
投稿日時: 2004-03-28 11:33
みなさんご返答ありがとうございます。

みなさんのご意見を参考にもう少しメモリ管理の方法を勉強したいと思います。
すこし、私の中で混乱してきたので整理してみます。

またのご意見をよろしくお願いします。


なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-03-28 11:54
ちょいと脱線します、すみません。

引用:

Jittaさんの書き込み (2004-03-28 08:07) より:
 う〜ん、その説明ではわかりにくいかも。

 ここで「資源」は「アンマネージドリソース」です。メモリも、newで確保した分は“マネージドリソース”なので、Dispose不要です。が、Win32API呼び出しを利用して、GlobalAllocateなどをした場合は、“アンマネージドメモリ”になるので、Diposeできるようにすることが必要です。


あ、そう、単に確保しているメモリって書いたのはマネージドメモリの事です。
# .NET Framework での話なので、単にメモリと書いた場合はその意味のつもりでした。

で、MSDN等にもIDisposableはアンマネージリソースの開放のために使用すると書かれてるんですが、場合によっては必ずしもそうとは限らないのでは?って思います。
まあ、大抵(ほとんど?)のケースでは最終的にはアンマネージリソースが関わってきますし、IDisposableの存在理由のメインはアンマネージリソースのためにあるのは事実ですが。

たとえば何らかのデータを収集するクラスがあったとして、収集が終わってインスタンスを開放する際には収集したデータをファイルに書き出さなくてはならないというとき、このクラスは決定的な破棄のタイミングを持つことが必要になります。
基本的にはFlushとかSaveとかいったメソッドを用意する事になりますが、.NET の決定的破棄の機構にインターフェイスをあわせるために、IDisposable.Disposeを同等の機能として提供するのはありかなと思います。
# C#だとusingが使えるようになりますし。

ファイル書き込みならアンマネージじゃないかって突っ込みがありそうですが、このクラス自身がアンマネージリソースを確保しているわけではありません。最後の破棄(フラッシュ)メソッドがアンマネージリソースをその場で使用するだけで、普段は確保していません。
あるいはファイルではなく、アプリ共有用のメモリに移動するというような処理でもいいです。

まあ、あくまでDisposeは「アンマネージリソースの破棄」という目的でなくてはならないのだって言われると、それを否定する根拠もないわけですから、最終的には使う人の判断ですが。
ただ、アンマネージリソースを持つクラスはDisposeが使えて、持たないクラスで決定的破棄タイミングでの処理が必要な場合は別の手段でなくてはならないとなれば、なんとなく手順に統一が取れずいやだなあと思います。

--修正
引用ミス修正

[ メッセージ編集済み 編集者: なちゃ 編集日時 2004-03-28 11:56 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-03-29 09:15
脱線失礼:
引用:

なちゃさんの書き込み (2004-03-28 11:54) より:


 まず、ごめんなさい。出かける前にちょこちょこ書いて、読み返さずにあげてしました。決して否定する意味で書いたわけではありません。

引用:

基本的にはFlushとかSaveとかいったメソッドを用意する事になりますが、.NET の決定的破棄の機構にインターフェイスをあわせるために、IDisposable.Disposeを同等の機能として提供するのはありかなと思います。


なるほど。アンマネージドメモリを使用する場合の「最終処理」としてDisposeを使うのだから、マネージドメモリでも「最終処理」を行う場合にそれに倣う、と。VB.NETでも、次のバージョンからusingが使えるそうですし。。。

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