web-dev-qa-db-ja.com

.Net / C#オブジェクトはそれ自体でDispose()を呼び出す必要がありますか?

以下は、同僚によって書かれたサンプルコードです。これは明らかに私には間違っているようですが、確認したかったのです。オブジェクトは、独自のメソッドの1つから独自のDispose()メソッドを呼び出す必要がありますか?オブジェクト自体ではなく、オブジェクトで行われた場合、オブジェクトの所有者/作成者のみがDispose()を呼び出す必要があるように思われます。

これは、完了時にそれ自体でDispose()を呼び出す.asmxWebメソッドです。 (これがWebメソッドであるという事実は、おそらく一般的な質問に付随するものです。)コードベースでは、他のWebサービスのメソッド内でWebサービスクラスをインスタンス化し、それらのメソッドを呼び出すことがあります。私のコードがこのメソッドを呼び出すためにそれを行う場合、メソッドが戻ったときにオブジェクトはトーストされ、実際にはオブジェクトを使用できなくなります。

[WebMethod]
public string MyWebMethod()
{
    try
    {
        return doSomething();
    }
    catch(Exception exception)
    {
        return string.Empty;
    }
    finally
    {
        Dispose(true);
    }
}

更新:関連するいくつかのリンクが見つかりました:

ASP.NETでWebサービス参照を破棄する必要がありますか?

Webサービスプロキシクラスを破棄しますか?

34
Tom Winter

確かにそれは良い習慣ではありません。呼び出し元は、オブジェクト自体ではなく、IDisposableオブジェクトの使用をいつ終了するかを決定する必要があります。

34
EvgK

私のプロジェクトの1つでそれを見たことがあれば、その理由を尋ねると、とにかくそれを削除すると99.9999%確信しています。

私にとってこれは一種の 赤い旗/コードの臭い

4
Fredou

「自己処分」アクションを実行する正当な理由はほとんどありません。スレッドは私がよく使うものです。

スレッドを「起動して忘れる」アプリケーションがいくつかあります。この方法を使用すると、オブジェクトを自己処理できます。

これにより、スレッドマネージャープロセスなしで環境をクリーンに保つことができます。

4
Tuk

Disposeメソッドで実行できることについて技術的な制限はありません。それについて特別なことは、Disposeが特定の構造(foreachusing)で呼び出されることだけです。そのため、Disposeは、特に呼び出しがべき等である場合に、オブジェクトに使用できなくなったことを示すフラグを立てるために合理的に使用される可能性があります。

ただし、Disposeのセマンティクスが受け入れられているため、この目的には使用しません。クラス自体の中からオブジェクトを使用できなくなったものとしてマークしたい場合は、Disposeまたは他の場所から呼び出すことができるMarkUnuseable()メソッドを作成します。

Disposeの呼び出しを一般的に受け入れられているパターンに制限することで、すべてのクラスのDisposeメソッドに変更を加える機能を購入し、共通のパターンから逸脱するコードを予期せず壊さないようにすることができます。

1

それを削除するだけですが、それを呼び出すすべてのオブジェクトに廃棄するように注意してください。

技術的にはそうです。その「メソッド」がファイナライザーであり、Microsoftによって指定された ファイナライズおよびIDisposableパターン を実装している場合。

0
Slugart

番号!これは予期しない動作であり、ベストプラクティスのガイドラインに違反しています。思いがけないことは絶対にしないでください。オブジェクトは、呼び出し元のオブジェクトの整合性を保護しながら、その状態を維持するために必要なことだけを実行する必要があります。呼び出し元は、いつ完了するか(または、他に何もない場合はGC)を決定します。

0
Dustin Davis

.Netオブジェクトは通常それ自体でDisposeを呼び出すことはありませんが、オブジェクト内で実行されているコードが、それを使用することを期待する最後のものである場合があります。簡単な例として、Disposeメソッドが部分的に構築されたオブジェクトのクリーンアップを処理できる場合、コンストラクターに次のようにコーディングさせると便利な場合があります。

 Sub New()
 Dim OK As Boolean = False 
 Try 
 ... do Stuff 
 OK = True 
最後に
 OKでない場合は、Me.Dispose 
 End Try 
 End Sub 

コンストラクターが返さずに例外をスローする場合、放棄が予定されている部分的に構築されたオブジェクトは、必要なクリーンアップを実行するための情報と推進力を持つ唯一のものになります。タイムリーな廃棄を保証しない場合、他に何もしません。

特定のコードに関しては、パターンはやや珍しいものですが、ソケットが1つのスレッドから別のスレッドに渡される方法のように見えます。バイトの配列を返し、ソケットを無効にする呼び出しがあります。そのバイト配列を別のスレッドで使用して、他のソケットによって確立された通信ストリームを引き継ぐ新しいソケットインスタンスを作成できます。開いているソケットに関するデータは事実上管理されていないリソースですが、ガベージコレクターが認識できないものに渡されることが多いため、ファイナライザーを使用してオブジェクトにラップすることはできません。

0
supercat