[C#] デストラクタとDisposeについて

**もくじ**
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f

**Dispose関連**
- [【C#】Disposeとは？](https://qiita.com/tera1707/items/d066672f834e296a9e40)
- [[C#] デストラクタとDisposeについて](https://qiita.com/tera1707/items/1b41ae8f38884656b9fb)


# やりたいこと
Disposeできるクラスを書くためにIDisposableのインターフェースを実装しようと思い、IDisposableでAlt+Enterを押し、「Disposeパターンを使ってインターフェースを実装します」を選択して、出てきたコードの中に「上の Dispose(bool disposing) にアンマネージ リソースを解放するコードが含まれる場合にのみ、ファイナライザーをオーバーライドします。」という文言が、自分が「デストラクタ」だと思っているもの(~MyClass()のところ)に書かれているのを発見。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/94d1c8df-e070-ea10-80bf-438a060b71be.png)

デストラクタ？ファイナライザ？これって何が違うのか？
あとDispose()の中でDispose(bool)を読んだりしているが、なんでそんなもの分けて作ってるのか？
ファイナライザ？の中で呼んでいるDispose(false)は何なのか？となったので、それぞれどういうものなのかはっきりしたい。

# しらべたこと
はっきり言って、100%は理解できてない。主に

- 「デストラクタ」と「ファイナライザ」の違いはなにか？
- C#でDisupose()をちゃんと実装するには？

ということを調べたので、現状の理解をまとめておく。
中途半端な内容で恐縮ですが、間違いなどあれば、ご指摘頂ければ幸いです。

### 用語としての**ファイナライザー**
**多くの場合、**下記のようなものを指す。

- GCに回収された時点で呼ばれるメソッド。
- 自分で呼ばれるタイミングを制御できない。

### 用語としての**デストラクタ**
**多くの場合、**下記のようなものを指す。

- newしたものをdeleteしたときに呼ばれるメソッド。(スコープから外れたときも)
- そのため、自分で呼ばれるタイミングを制御できる。

### C#のファイナライザー
- C#にはファイナライザーを書く書き方(文法)「は存在しない。なので存在する(書ける)のはデストラクタのみ。
- C#では、MyClassクラスであれば「~MyClass()」と書いてデストラクタとなる。これが、GCに回収されるときに呼ばれるメソッドとなる。(ファイナライザ的な動作をする)
- ++C++のサイトでは、これのことを「デストラクター」と呼んでいる。[こちら](https://ufcpp.net/study/csharp/resource/rm_destructor/)参照。
- C++/CLIには、デストラクタとファイナライザの両方を書く文法があるが、C#はデストラクタのみ。
- VisualStudioでIDisposableインターフェースを実装するときに「Disposeパターンを使ってインターフェースを実装します」を選択してでてくるコードのコメントの中ではこれのことを「ファイナライザ」と呼んでいるので、混乱してしまう。
- C++のデストラクタとC#のファイナライザー(の役割をするデストラクタ)の書き方が同じなので、また混乱してしまう。
- javaに、finalizeメソッドというのがあり、それが「GCに回収された時点で呼ばれる」メソッドである。C#の~~ファイナライザー~~デストラクタはそれと同じような動きをする。

### C#での実装方法
- Disposeについて
  - Disposeできるクラスを作成するには、IDisposableインターフェースを実装する。 
  - 基本的には、Disposeは、例えばFileStreamクラスを使用して開いたファイルを使い終わったら閉じる、のように、ユーザーが自分のタイミングで使ったリソースの占有を止めるときに呼ぶものである。
  - これを便利に書く書き方が、`using()`である。(usingが終わったら、書かなくてもDisposeしてくれる)
- IDisposableの実装について
  - 自分でDisposeできるクラスを実装するときに、ALT+ENTを押して「Disposeパターンを使ってインターフェースを実装します」を選ぶと、Disposeパターンを自動で書いてくれる。
  - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/e5ad691b-7b9f-a03a-900c-2694895e1dec.png)


  - その中のDispose(bool)について、
     - Dispose(true)が、Disposeで呼ばれるメソッドになる。(なる、というか、そのようにする)
     - Dispose(false)が、デストラクタ(やってることとしてはファイナライザ)で呼ばれるものになる。(する)
    - [こちら](https://ufcpp.net/study/csharp/rm_disposable.html?sec=idisposable#idisposable)が詳しい。
  - やっている内容としては、マネージ/アンマネージのリソースの後処理。下記の通り。
- マネージ/アンマネージの解放について
  - デストラクタ(~MyClass()と書くやつ)には、
     - マネージリソースの解放処理を書かない。
     - アンマネージリソースの解放処理を書く。
     - ※デストラクタでDispose(false)を呼んだ時に、これをするように作る。
  - Disposeの実装には、
     - マネージリソースの解放処理を書く。
     - アンマネージリソースの解放処理も書く。
     - ※Dispose(引数なし)でDispose(true)を呼んだ時に、これをするように作る。
- アンマネージのリソースをデストラクタにも書くのは、(もしDisposeでの開放が行われなかった場合でも)確実に開放を行うため。
- アンマネージドのリソースが無い場合は、デストラクタを書かなくてもよい。(Disposeパターンで出てくるひな形の通り、コメントアウトでOK)

# 備考
知りたいことは、下の「参考」のところに書かせて頂いたページにすべて書いてあるのだが、自分の現状の理解をまとめたかった次第。

# 参考
MsDocs デストラクタについて
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/destructors

MsDoscs ファイナライザーについて
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/destructors
→「ファイナライザー」の別名が「デストラクタ」だと言ってる。

デストラクター(++C++)
https://ufcpp.net/study/csharp/resource/rm_destructor/

IDisposable インターフェイスの実装
https://ufcpp.net/study/csharp/rm_disposable.html?sec=idisposable#idisposable
＞「IDisposable インターフェイスの実装」の項目。

C# のファイナライザ、Dispose() メソッド、IDisposable インターフェースについて
https://qiita.com/Zuishin/items/9efc9c8cbb98300bbc64

デストラクタ
Wikipedia。ここでファイナライザについても言及されている。
https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF
＞「ファイナライザ」の項を参照。短い文章だが、なんかしっくりきた。