- - PR -
インスタンスがスコープから外れる時に終了処理を確実に実行する方法
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-03-05 19:07
要件
(1) インスタンスがスコープから外れるタイミングで確実に終了処理を実行したい。 (2) 終了処理の実行を明示的に指示しなくて済むようにしたい。 更に (3) 新たなコンストラクタによって再初期化される前の値(つまりまさに消滅しようとしているインスタンスが持っている情報)を使って終了処理をしたい。(Example3) 更に (4) 常に終了処理が完了するのを待って新たなコンストラクタによる再初期化が開始されようにしたい。 確かに、要件(1)(2)だけであれば、Example1のようにTestクラスを定義をして、 Example2のように使用をすることで一応満足できますが、 要件(3)、つまりExample3のように記述できるほうがよりエレガントです。 ところが、Dispose()の中でコンストラクタで初期化したパラメータを使用しなくては ならない場合、正常に処理することができません。 Dispose()はいつ実行されるか分からないためコンストラクタで再初期化した後の値が 参照される可能性があります。 更に 可能であるなら、要件(4)にあるような、厳しいタイミング制御もできればと思っています。 良い工夫(つまりTestクラスの記述方法)はないでしょうか? // *** Exsample1 *** public class Test : IDisposable { public Test(int p) { thisP = p; // 初期化処理 … } public void Dispose() { // 終了処理 // コンストラクタで与えられた"thisP"を使って記述したい … } private int thisP; } // *** Example2 *** public class Main { public void Exec() { Test test; … test = new Test(123); … test.Dispose(); // Test(123)の終了処理 test = new Test(345); … test.Dispose(); // Test(345)の終了処理 test = new Test(567); … test.Dispose(); // Test(567)の終了処理 } } // *** Example3 *** public class Main { public void Exec() { // *** 明示的に指示しなくてもインスタンスが廃棄されると // 自動的にDispose()が機能するようにしたい *** Test test; test = new Test(345); … test = new Test(567); … test = new Test(678); … } } | ||||
|
投稿日時: 2005-03-05 19:16
文書の記入にミスがありました。下記のように訂正します。
質問1 要件(1)(2)(3)全てを満たす方法を知りたい 質問2 要件(1)(2)(3)(4)全てを満たす方法を知りたい 要件 (1) インスタンスがスコープから外れるタイミングで確実に終了処理を実行したい。 更に (2) 終了処理の実行を明示的に指示しなくて済むようにしたい。 (3) 新たなコンストラクタによって再初期化される前の値(つまりまさに消滅しようとしているインスタンスが持っている情報)を使って終了処理をしたい。(Example3) 更に (4) 常に終了処理が完了するのを待って新たなコンストラクタによる再初期化が開始されようにしたい。 確かに、要件(1)だけであれば、Example1のようにTestクラスを定義をして、 Example2のように使用をすることで一応満足できますが、 要件(2)、つまりExample3のように記述できるほうがよりエレガントです。 ところが、要件(3)のようなケースでは、Dispose()の中でコンストラクタで初期化したパラメータを使用しなくてはならない場合、正常に処理することができません。 Dispose()はいつ実行されるか分からないためコンストラクタで再初期化した後の値が 参照される可能性があります。 更に 可能であるなら、要件(4)にあるような、厳しいタイミング制御もできればと思っています。 良い工夫(つまりTestクラスの記述方法)はないでしょうか? // *** Exsample1 *** public class Test : IDisposable { public Test(int p) { thisP = p; // 初期化処理 … } public void Dispose() { // 終了処理 // コンストラクタで与えられた"thisP"を使って記述したい … } private int thisP; } // *** Example2 *** public class Main { public void Exec() { Test test; … test = new Test(123); … test.Dispose(); // Test(123)の終了処理 test = new Test(345); … test.Dispose(); // Test(345)の終了処理 test = new Test(567); … test.Dispose(); // Test(567)の終了処理 } } // *** Example3 *** public class Main { public void Exec() { // *** 明示的に指示しなくてもインスタンスが廃棄されると // 自動的にDispose()が機能するようにしたい *** Test test; test = new Test(345); … test = new Test(567); … test = new Test(678); … } } _________________ | ||||
|
投稿日時: 2005-03-05 19:21
using
_________________ 中博俊 MSMVP Visual Studio C# Since 2004/04-2005/03, MCP http://naka.wankuma.com/ http://blogs.wankuma.com/naka/ naka@wankuma.com | ||||
|
投稿日時: 2005-03-05 19:30
こんにちは、じゃんぬねっと です。
ちなみに、VB.NET, J# なら、Finally。 こんな感じで。 http://jeanne.wankuma.com/tips/dialog/04-folderbrowser.html _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||
|
投稿日時: 2005-03-07 15:30
ご指摘のとおり、C# の using(object){…} で記述できました。
ありがとうございました。 | ||||
|
投稿日時: 2005-03-07 18:46
> 終了処理の実行を明示的に指示しなくて済むようにしたい。
無理です。いつ終了させたいのかは、開発者しか知らないからです。 Ex.2のコードですが、インスタンスを破棄している(破棄したいと思っている)のは開発者で、コードはインスタンスを破棄してはいません。Disposeメソッドは、アンマネージリソース解放を指示するメソッドで、インスタンスを破棄するメソッドではありません。.NET Frameworkにおいて、インスタンスを破棄するタイミングは不明です。CLRが管理しています。しかし、C#、C++ではデストラクタ、VB.NETではファイナライザを明示的に呼び出すことで、破棄することが出来ます。デストラクタ(ファイナライザ)で終了処理を呼び出すように定義していれば、インスタンスが破棄されるタイミングで終了処理が行われるため、クラス使用者は終了処理の実行を明示的に指示する必要はありません。もちろん、インスタンスの破棄は、明示的に行う必要があります。 > ところが、要件(3)のようなケースでは、Dispose()の中で > コンストラクタで初期化したパラメータを使用しなくてはならない場合、 > 正常に処理することができません。 > Dispose()はいつ実行されるか分からないためコンストラクタで > 再初期化した後の値が参照される可能性があります。 ほとんど間違い。 複数のインスタンスで共通する値は使われません。各インスタンスで変数の値は独立しています。そうでなければプログラムが成り立ちません。もっとも、クラス変数を定義していれば、クラス変数はすべてのインスタンスで共通して使われます。「ほとんど」としたのは、クラス変数なのか、インスタンス変数なのか、明示されていないからです。 Disposeは、開発者が呼び出せば、その時に実行されます。逆に、呼び出さなければ、実行されません。したがって、『いつ実行されるかわからない』というのは誤り。ただし、IDisposableインタフェースを実装する場合、デストラクタ(ファイナライザ)でDiposeメソッドをコールし、確実にDiposeメソッドが実行されるようにする必要があります。このため、デストラクタ(ファイナライザ)が『いつ実行されるかわからない』ので、デストラクタ(ファイナライザ)で実行されるようにコード上はDisposeしなかったインスタンスのDisposeメソッドが、いつ実行されるかわからないという意味では正解。 デストラクタ(ファイナライザ)と、Disposeは違います。注意してください。 で、この案件ですが、どちらかというと、シングルトンパターンの応用???
|
1