1

IDictionary インスタンス メンバーを介して他のクラスへの参照を保持するクラスがいくつかあります。

そのようです:

class A
{
  private readonly Dictionary<int, B> _particles = new Dictionary<int, B>();
  public void CreateNewB(int someInt)
   {
     var b = new B();
     if (!_particles.ContainsKey(someInt)
         _particles.Add(someInt, b);
   }
}

これがセットアップであり、この辞書からそれらを削除することは決してありませんが、何らかの理由で、クラス B のデストラクタが GC の実行で時々呼び出され、その理由がわかりません。

Dictionary クラスが新しい参照を追加する方法と関係があるのでしょうか?

固定:

わかりました、あなたの答えをありがとう、私は確かに今GCとデコンストラクターについて大きな理解を得ています.

しかし、問題は私自身のものでした.someIntがまだ存在しない場合にのみ追加し、ビジネスロジックに欠陥があるため、someIntは常に1だったので、初めて機能し、デコンストラクターが呼び出されませんでした. しかし、2 回目は "b" インスタンスがリストに追加されず、GC 実行でクリーンアップされました。

助けてくれたすべての人にもう一度感謝します!

4

6 に答える 6

3

クラスAへの参照が死んでいる場合、クラスBはGCになります

于 2009-11-30T03:14:46.943 に答える
1

この辞書からそれらを削除することは決してありませんが、何らかの理由で、クラス B のデストラクタが呼び出されます

.NET のデストラクタは、C++ (非マネージ) のデストラクタと同じではありません。
デストラクタは自動的にFinalizeメソッドを呼び出します。

デストラクタの特徴を次に示します。

  • デストラクタは構造体で定義できません。それらはクラスでのみ使用されます。
  • クラスは、デストラクタを 1 つだけ持つことができます。
  • デストラクタは、継承またはオーバーロードできません。
  • デストラクタは呼び出せません。それらは自動的に呼び出されます
  • デストラクタは修飾子やパラメータを取りません。

したがって、あなたの場合に何が起こっているかは次のとおりです(2語で):

  1. クラス A はガベージ コレクションです。
  2. 1 の結果: _particles フィールドは GC-d を取得します。
  3. 2 の結果として、ディクショナリのエントリがルート化されなくなりました (ガベージ コレクションで使用可能)。
  4. 3 の結果として、ディクショナリのエントリ (クラス B インスタンス) は GC-d です。

Dictionary クラスが新しい参照を追加する方法と関係があるのでしょうか?

いいえ。

于 2009-11-30T03:27:50.097 に答える
1

あなたは何か非常に間違ったことをしているように聞こえます。管理された環境では、これらのオブジェクトを実際に保持するつもりがない限り、本質的に永久に存続する参照をこのように保持すると、メモリ リークが発生します。

ここで覚えておくべきもう 1 つのことは、C# にはデストラクタのようなものがないということです。あなたが持っているのはファイナライザーであり、これは異なります。マネージ コードでは、ファイナライザーの作成が必要になることはほとんどありません。これを行う唯一の正当な理由は、型に IDisposable を実装して、まだ finalizer でカバーされていないアンマネージ リソースをラップする場合です。

たとえば、多くの人が IDisposable を実装し、データ アクセス レイヤーの一部として SqlConnection をラップする型を作成します。このようにして、ブロックを使用して型のインスタンスをラップし、作成した SqlConnections が適切に破棄されるようにすることができます。ただし、基になるデータベース接続は SqlConnection クラス自体のファイナライザーによって既にカバーされているため、この型にはファイナライザーは必要ありません。心配する必要がある新しいアンマネージ リソース タイプはありません。SqlConnection タイプだけです。しかし、まったく新しいデータベース エンジンを構築し、そのために新しい .Net データ プロバイダーを実装する場合は、接続用のファイナライザーを実装する必要があります。

于 2009-11-30T03:56:28.667 に答える
0

わかりました、あなたの答えをありがとう、私は確かに今GCとデコンストラクターについて大きな理解を得ています.

しかし、問題は私自身のものでした.someIntがまだ存在しない場合にのみ追加し、ビジネスロジックに欠陥があるため、someIntは常に1だったので、初めて機能し、デコンストラクターが呼び出されませんでした. しかし、2 回目は "b" インスタンスがリストに追加されず、GC 実行でクリーンアップされました。

私はそれを締めくくるためにこれに答えています:)

于 2009-12-10T03:02:50.437 に答える
0

だから私は次のタイプを持っています:

type k {
public k() { Console.WriteLine("Hi, I'm a new K!"); }
public ~k() { Console.WriteLine("I'm a dying K!"); }
}

コードの小さなスニペット:

Dictionary<int, k> ks = new Dictionary<int, k);
for(int i=0;i<10;i++) { ks.add(i, new k()); }

~k() がある時点で呼び出されているのがわかりますか? それは何が起こっているのですか?

于 2009-11-30T03:44:06.150 に答える
-2

B他の場所で作成されているクラスにお金を賭けます。Bコンソール アプリの場合は、コンストラクターとファイナライザーで何かを出力します。インスタンス化の数が期待どおりであることを確認してください。

于 2009-11-30T03:40:30.277 に答える