15050


[Disposeパターン](https://ja.stackoverflow.com/questions/15036/idisposable-%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B%E3%81%B9%E3%81%8D%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B)にてマネージリソースとアンマネージリソースの解放方法に違いがありますが、`FileStream`
はどちらとして扱うべきでしょうか？


CC BY-SA 3.0
2015-08-30T12:18:40.727
15038
2022-06-26T11:05:36.390
2017-04-13T12:52:39.113
-1
8870
question
c#
FileStream はマネージリソースとアンマネージリソースのどちらでしょうか？


アンマネージリソースを保持する`IDisposable`オブジェクトはマネージリソースの範疇に入ります。


CC BY-SA 3.0
2015-08-30T12:33:29.490
15040
2015-08-30T12:33:29.490
5750
15038
answer


FileStreamの内部では、もちろんアンマネージリソースを抱えていますが、閉じ込めていますので  
利用者から見れば、マネージリソースになります。


CC BY-SA 3.0
2015-08-30T13:43:14.900
15048
2015-08-30T13:43:14.900
2207
15038
answer


マネージリソースではありますがDispose()すべきです。

次のようなクラスを考えます。

[code]

    class SomeClass {
        private FileStream file;
        ...
    }
    
[/code]

fileの使用を終えたとしてもSomeClassインスタンスから参照されているためこのFileStreamは解放されません。またSomeClass利用者が明示的に解放したくてもアクセスできません。その結果、FileStreamはGCに回収されるまで解放されません。  
このような問題があるため、
**IDisposableを実装するインスタンスを保持するクラスは同じくIDisposableを実装し、保持しているIDisposableインスタンスをすべて解放すべき**
です。

このことはマネージコード分析において [CA1001:
破棄可能なフィールドを所有する型は、破棄可能でなければなりません](https://msdn.microsoft.com/ja-
jp/library/ms182172.aspx) 警告の対象となっていることからもわかります。

* * *

指摘があったので補足します。  
Diposableパターンそのままで実装してしまうとデストラクターからDispose()メソッドが呼ばれてしまいますが、SomeClass自身にはアンマネージリソースを保持していないためパフォーマンスの無駄となってしまいます。  
しかし、クラス利用者からDispose()可能とする必要があるためIDisposableを実装する点は変わりませんが、Disposableパターンに従わず、Dispose()メソッドだけを実装することになるでしょうか。


CC BY-SA 3.0
2015-08-30T14:03:58.723
15049
2015-08-30T21:09:19.133
2015-08-30T21:09:19.133
4236
4236
15038
answer


マネージリソースは .NET のランタイム（CLR）によって管理（マネージ）されているリソースで、その解放処理は **CLRが責任を持ちます**
。また、その大半はGCの対象になっています。

一方アンマネージリソースはネイティブAPIで直接確保したリソースなどが該当します。これらの確保・解放にCLRは関与しないため、 **利用者が責任を持って**
解放する必要があります。

直接・間接的にアンマネージリソースを確保していようが、CLRの管理下にあるオブジェクトはマネージリソースと言えます。故に `FileStream`
オブジェクトはマネージリソースです。

* * *

マネージリソースはいつかは解放されるわけですが、メモリを大量に消費するリソースや、排他的に確保されるリソースなど、自動的な解放を待っていられない場合があります。そのような場合に手動で解放するのが
`IDisposable.Dispose()` です。

なのでこれが呼び出された場合には、そのオブジェクトが保持するアンマネージリソースのみならず、メモリを大きく消費するマネージリソースや、
`IDisposable` オブジェクトをすぐに解放する必要があります。これが Dispose パターンの `Dispose(bool)`
内で行うマネージオブジェクトの解放です。

  * [Dispose Pattern - MSDN Library](https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/implementing-dispose)
  * [CLRから見たリソースについて - 荒井省三のBlog - Site Home - MSDN Blogs](https://web.archive.org/web/20140418052138/http://blogs.msdn.com/b/shozoa/archive/2010/09/08/about-resources-on-clr.aspx)


CC BY-SA 4.0
2015-08-30T14:14:50.013
15050
2022-06-26T11:05:36.390
2022-06-26T11:05:36.390
19769
8000
15038
answer


FileStreamなど、アンマネージリソースを使うインスタンスの解放にはusing句を使いましょう。  
using句を使うとスコープを抜けるときにDispose()が呼び出されますよ。


CC BY-SA 3.0
2015-08-30T14:31:22.520
15051
2015-08-30T14:31:22.520
11136
15038
answer