2

IDisposableの実装がいつ必要かを理解しようとしています。

ちょっとした例を書きました。

  public class FileManager
  {
    private FileStream fileStream;
    public void OpenFile(string path)
    {
       this.fileStream = File.Open(path, FileMode.Open, FileAccess.Read);
    }
    public void CloseFile(string path)
    {
      if ( this.fileStream != null && this.fileStream.CanRead)
      {
        this.fileStream.Close();          
      }
      this.fileStream.Dispose();
    }
  }

// client
var manager = new FileManager();
manager.Open("path");
manager.Close("path");

このクラスには、アンマネージリソース(ファイル)を保持するマネージリソース(FileStream)があるため、IDisposableを実装する必要がありますか?または、クラス内でクリーンアップしているため、IDisposableを実装する必要はありませんか?

混乱している。

4

6 に答える 6

5

IDisposable自明ではない方法で実装し、実装する可能性のある型のすべてのインスタンスについて、そのインスタンスがどのようになるかをいつでも識別できる必要がありますDispose。ほとんどの場合、これは、各IDisposableインスタンスに明確に定義された所有者がいて、 の呼び出しを担当することを意味しますDispose。クラスによって作成されたインスタンスの場合、FileStream他に何もできないため、クラスが所有者になりDisposeます。

所有IDisposableするインスタンスを参照するフィールドを持つクラスは、ほとんどの場合、 を実装し、所有するオブジェクトに対してメソッドを使用する必要があります。あなたのクラスにはそのようなフィールドがあります。したがって、実装する必要があります。IDisposableDisposeDisposeIDisposableIDisposable

可能な限り、クリーンアップを必要とするクラスは、そのクラスを呼び出すだけIDisposable.Disposeで、必要に応じてすべてのクリーンアップを実行できるように設計する必要があります。場合によっては、他の方法を使用せずにクリーンアップを実行することが現実的でない場合もありますが、そのようなケースは非常にまれです。Dispose必要なすべてのクリーンアップを処理するクラスを設計できる場合は、そうする必要があります。

于 2012-06-08T21:37:19.403 に答える
1

あなた (または別の開発者) が FileManager クラスを使用していて、それを閉じるのを忘れた場合に備えて、IDisposable を実装することをお勧めします。IDisposableの例でファイナライザーに呼び出しを入れる方法に注意してくださいDispose(false)

于 2012-06-08T21:23:51.720 に答える
1

close メソッドにパスを渡すのはなぜですか? あなたの場合、別のファイルを開く前に閉じている場合、マネージャーは別のファイルを開くことができるようです。そのため、そのオブジェクトを破棄したくありません。

私見、私はそれをこのように実装したいと思います:

public class FileManager : IDisposable
{
    private string path;
    private FileStream fileStream;
    public FileManager(string path) 
    {
       this.path = path;
    }
    public void OpenFile()
    {
       this.fileStream = File.Open(path, FileMode.Open, FileAccess.Read);
    }
    public void CloseFile()
    {
      if ( this.fileStream != null && this.fileStream.CanRead)
      {
        this.fileStream.Close();
        this.fileStream.Dispose();
      }
    }

    public void Dispose(){
        this.CloseFile();
    }
}

// client
var manager = new FileManager("path")){
manager.OpenFile();
//Do other stuff
manager.CloseFile()

また

using( var manager = new FileManager("path")){
    manager.OpenFile();
    //Do other stuff
}
于 2012-06-08T21:23:55.863 に答える
1

メソッドを呼び出す場合はClose、個別に破棄する必要はありません。ただし、この場合の一般的な方法IDisposableは、クラスのコンシューマーが を呼び出すという保証がないため、実装することCloseです。

リソースが作成され、同じメソッド内で破棄される場合にのみ、確実に除外IDisposableできます。これは、リソースが使用後に確実に破棄されることを確認できる唯一の方法だからです。

于 2012-06-08T21:24:41.120 に答える
1

IDisposable を実装する必要があります。

想像:

var manager = new FileManager();
manager.Open("path"); // <- throws for some reason
manager.Close(); // <- then this never gets called

もちろん、次のように try/finally を配置することもできます。

try {
  var manager = new FileManager();
  manager.Open("path");
}
finally {
  manager.Close();
}

...しかし、それはまさに using と IDisposable が発明されたものであり、快適に書くことができます:

using (var manager = new Manager()) {
  manager.OpenFile("path");
} // and CloseFile will automagically be called here.
于 2012-06-08T21:31:10.317 に答える
0

宣言的なものではないにしても、ここで実装しても実際の利点は見られません。IDisposable誰かがあなたのクラスの実装を見た場合IDisposable、使用後にクリーンアップする必要があるリソースがどこかにあることを理解しています。これは、.netこのような型を宣言する組み込みの規則にすぎません。

そのパターンを使用しない場合は、自由にそれを行うことができますが、提案された型宣言に違反し、主にコミュニティの.net型宣言に従っています。

于 2012-06-08T21:22:41.747 に答える