動的オブジェクトの場合のガベージコレクション

Foo a;

try
{
//some work with a;
}
finally
{
 a = null;
}

この例では、オブジェクトaにガベージコレクションをマークします。

ここで、このようなコードを修正するとします。

public  xyz()
{
 return new Foo();
}

この例では、新しく作成されたオブジェクトには名前がないので、いつコレクションにマークされますか?またはGCが自動的に使用していないと判断し、回復しようとしますか?

編集:

答えを読んだ後、私はもう一つの状況を追加しています。

Foo a;

try
{     
  return a;
}
finally
{
 a = null;
}

今何が起こるでしょうか?

2
xyz()、btwの戻り値の型は何ですか? 'cos public xyz(){新しいFoo()を返します。 } は決して有効ではありません...
追加された 著者 Marc Gravell,
xyz がクラスであれば、戻り値の型は関係ありません - あなたが呼び出す項目にかかわらずオブジェクトです。 xyz が構造体の場合、 object / dynamic /an-interfaceは boxing コレクションを必要とするオブジェクトを追加する
追加された 著者 Marc Gravell,
@MarcGravell - 型が問題であれば、その型がガベージコレクションで問題を抱えていることを知りませんでしたので、その型も重要です。
追加された 著者 harrisunderwork,

5 答え

ガベージコレクションのマークは決してありません」...これはオブジェクトであり、GCがそれを考慮するのに十分な十分なです。フィールドと変数に割り当てることは、正常に収集できる場合にのみ影響を与えます。

第2の例に関して:

  • 値として( xyz()からの戻り値として)スタックにある場合、それは収集されません。
  • ローカル変数に保持されている場合は収集されません(GC実装に応じて、変数が再度読み込みされているかどうかによって異なります)。
  • 到達可能なオブジェクト(収集できないオブジェクト)のフィールドとして保持されている場合、そのオブジェクトは収集されません。
4
追加された

この例では、オブジェクトaにガベージコレクションをマークします。

いいえ、あなたはしません。後でコードで変数を使用しない限り、ガベージコレクタは参照がもう使用されていないことを既に認識しています。最後の使用の後でオブジェクトを収集することができるので、参照をnullに設定する前にオブジェクトを収集することもできます。

参照をnullに設定しても、ガベージコレクタに関する限り、後でコードで変数を使用しない限り、何の効果もありません。

Foo a = new A();

try {
 //some work with a;
 //at this point a is no longer used, so it can be collected
} finally {
 //this has no effect on garbage collection:
  a = null;
}

オブジェクトをコレクティブにするためにオブジェクトに何もする必要はなく、使用をやめるだけで、オブジェクトは収集されます。

特殊な処理を必要とするオブジェクトは、 IDisposable インタフェースを実装するオブジェクトだけです。これらのオブジェクトが終了したら、それらのオブジェクトに対して Dispose メソッドを呼び出すか、 Dispose ブロックを自動的に呼び出す using

編集:

変数をnullに設定した追加のシナリオでは、ガベージコレクションにも影響しません。ローカル変数をnullに設定しています。これは、すでに渡されたオブジェクト参照には影響しません。

2
追加された
特別な扱いが必要な唯一のオブジェクトは、IDisposableインターフェイスを実装するものです。これらのオブジェクトの処理が完了したら、それらのオブジェクトに対してDisposeメソッドを呼び出すか、自動的にDisposeを呼び出すusingブロックに入れてください。
追加された 著者 harrisunderwork,

xyzの呼び出し元が何かに結果を代入すると、その結果が残ってしまいます。さもなければ、最終的にGCされます。 GCが生き残るためにオブジェクトの参照を保持するだけのものが必要です。

2
追加された
私は私の混乱を解消したと思う。オブジェクトが何かに引っかかっていない限り、それは後の時点で収集されます。右 ?
追加された 著者 harrisunderwork,

興味深い MSDNの記事をご覧くださいC#オブジェクトの寿命。

スニペット:

ガベージコレクタはオブジェクト参照をトレースし、オブジェクトを識別します   コードを実行してもアクセスできなくなる

これは、参照カウントを使用していないと明示的に言いますが、オブジェクトにアクセス可能な参照があるかどうかをスキャンする代替方法です。コードがオブジェクトにアクセスできない場合、そのコードは収集用にマークされています。

1
追加された
msdn.microsoft.com/en-us/library/ms973837.aspx - ここには、そのテーマに関するいくつかの読書資料があります。私は、コンパイラが "世代"を使ってオブジェクトの年齢を判断し、そのオブジェクトが参照のためにテストされる必要がある頻度を決定するのを助けることを知っています。
追加された 著者 Corey Ogburn,
メインの.NET CLRの@harrisunderwork GCは、非常に効率的な短期間のオブジェクト(つまり大多数)の特に "世代的"アプローチを使用します。
追加された 著者 Marc Gravell,
したがって、大きなコードでは、すべてのオブジェクトをトレースしますか?パフォーマンス上の問題を起こさないだろうか?
追加された 著者 harrisunderwork,
ありがとう@MarcGravell
追加された 著者 harrisunderwork,

Foo <; を書くと、スタック上の Foo 型のオブジェクトを参照するメモリだけが作成されます。

new Foo(); を書くと、参照なしのヒープ上に Foo 型のオブジェクトだけが作成されます。

Foo a = new Foo(); と書くと、ヒープ上のオブジェクト Foo を参照する a

enter image description here

a = null; を設定すると、Heapの Foo オブジェクトへの参照が削除され、参照はなくなります。

GCはこれ以上参照されないオブジェクトを収集します。

メソッド内でオブジェクトを作成し、メソッドから戻るときも同じです。
メソッド内で a のように作成したリファレンスは、返ってくるとスタックからクリアされ、メソッド内で作成したオブジェクトは参照されなくなります。 GCがそれを収集する。

0
追加された
うん、私はそれを理解した。オブジェクトが参照に貼られている限り、オブジェクトは収集されません。
追加された 著者 harrisunderwork,