質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

10689閲覧

C# IDisposeの実装;アンマネージ リソースとは?

aha1009

総合スコア11

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2018/07/27 08:38

前提・実現したいこと

C++で数値計算を行っていましたが、最近C#を始めました。
下記の認識で問題ないのか、認識違いをご教示ください。

C#の自作クラスはメモリ解放する必要性があると思うのですが、
いろいろなサイトを読んでも、マネージ/アンマネージリソースが
よく分かりませんでした。

1. C++のDeleteがない → GCが適宜開放する。
・ インスタンスへのアクセスがなくなる。
・ インスタンスポインタ=nullした場合。
・ インスタンスのDispose()を呼んだ場合。

2. 自作クラスには、IDisposeクラスを実装し、オブジェクトを開放する。
・ マネージリソース;.Netのライブラリ?(BitmapやStream)
・ アンマネージリソース;自作クラス?
・ intなどは関係ない?

Disposeの実装は下記でOKなのか?

C#

1 2 class Area {// 自作クラス 3 public double xS { get; set; } = -1; 4 public double xE { get; set; } = -1; 5 6 public double yS { get; set; } = -1; 7 public double yE { get; set; } = -1; 8 9 public Area() { } 10 11 public Area(Area src) { 12 //throw new NotImplementedException(); 13 this.xS = src.xS; 14 this.xE = src.xE; 15 this.yS = src.yS; 16 this.yE = src.yE; 17 return; 18 } 19 }// Area 20 21 class Analysis : IDisposable { 22 23 public Bitmap bitmap { get; set; } 24 public Area area { get; private set; } 25 private byte[] _pixels = null; 26 private int aaa; 27 28// 処理など 29 30 private bool disposedValue = false; // 重複する呼び出しを検出するには 31 protected virtual void Dispose(bool disposing) { 32 if (!disposedValue) { 33 if (disposing) { 34 if (bitmap == null) 35 bitmap.Dispose(); 36 } 37 area = null; 38 _pixels = null; 39 40 disposedValue = true; 41 } 42 } 43 44 public void Dispose() { 45 Dispose(true); 46 // GC.SuppressFinalize(this); 47 } 48 }

補足情報(FW/ツールのバージョンなど)

Win10 pro, VisualStudio 2015pro

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

詳しく解説するとめちゃくちゃ長くなってしまうので、だいたい99%の状況に適用できるルールを紹介します。

  • IDisposableが実装されているオブジェクトを自クラスの「フィールドに格納することがある」なら、自クラスにIDisposableを「必ず」実装し、Disposeが呼ばれたらそのフィールドのDisposeを呼ぶ
  • それ以外の場合、COMを呼んだりしなければIDisposableを実装することは「ほぼない」
  • 自クラスが何らかの「開始」と「終了」をペアで持つような性質がある場合、「開始」をコンストラクタで(またはInitializeとか)、そして「終了」をDisposeで行うようにIDisposableを実装する

このルールに則ってコーディングしてみると、IDisposableがどういうものなのか自然と分かってくると思います。
(あ、MSDNとかにデカデカと載ってる「Disposeパターン」ってのは、余程のローレベルプログラミングをしない限り書くことはないです。ぼくはまだ一度も書いたことない)

投稿2018/07/27 10:21

tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aha1009

2018/07/27 10:46

分かりやすいルールありがとうございます! 下記の認識であってますでしょうか。 1. フィールドはC++のメンバ変数のことで、 「public Bitmap bitmap { get; set; }」は「Disposableが実装されているオブジェクトを自クラスのフィールドに格納すること」 に該当する認識であってますか? 2. StreamやCOMなど通信系などで、「終了させたい」ときに実装する。 => 今回のケースでは、Bitmapを使用しなければ、IDisposeは不要。 ということであってますでしょうか。 以上、よろしくお願いします!
tamoto

2018/07/27 11:13 編集

ぜんぶあってます! 最後の「Bitmapを使用しなければ、」っていうのが「メンバ変数に枠を定義しなければ」っていう意味なら間違いないですが、メソッド内で「使うけど、メンバ変数には置かない」ってやつもIDisposableを定義する必要はないです!
aha1009

2018/07/30 00:14

おはようございます。 分かりました! ご教示ありがとうございました!
guest

0

このあたりが参考になるかと。".NET のクラスライブラリ設計"が出典ですし。

マネージメモリ (C# の new 演算子を使用して割り当てられたメモリ)

(中略)

マネージメモリ以外のリソースは、依然として明示的に解放される必要があり、「アンマネージリソース」と呼ばれます

なので、Areaとかは、if(disposing)の中でいいかと思います。

投稿2018/07/27 08:45

編集2018/07/27 08:47
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aha1009

2018/07/27 09:33

ご回答ありがとうございます! リンク先の末尾の https://blogs.msdn.microsoft.com/shozoa/2010/09/07/clr/ を読むと、インスタンスはすべてマネージリソースになるように感じました。 ご教示頂いた通り、 newしたものはすべてif(disposing)の中のほうが良さそうと分かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問