11

これらの関連リソースも参照してください。


言い換えると:

ローカル変数によって参照されているオブジェクトは、変数がスコープ外になる前に再利用できますか(たとえば、変数が割り当てられているが、再度使用されないため)、または変数が外れるまでガベージコレクションの対象外であることが保証されていますか?範囲?

説明させてください:


void Case_1()
{
    var weakRef = new WeakReference(new object());

    GC.Collect();  // <-- doesn't have to be an explicit call; just assume that
                   //     garbage collection would occur at this point.

    if (weakRef.IsAlive) ...
}

objectこのコード例では、明らかに、新しい'edがガベージコレクターによって再利用される可能性を計画する必要があります。したがって、ifステートメント。

weakRef(私は、新しい'edがまだ存在するかどうかを確認することのみを目的として使用していることに注意してくださいobject。)


void Case_2()
{
    var unusedLocalVar = new object();
    var weakRef = new WeakReference(unusedLocalVar);

    GC.Collect();  // <-- doesn't have to be an explicit call; just assume that
                   //     garbage collection would occur at this point.

    Debug.Assert(weakRef.IsAlive);
}

このコード例の前のコード例からの主な変更点は、new'edobjectがローカル変数(unusedLocalVar)によって強く参照されることです。weakRefただし、弱参照( )が作成された後は、この変数が再び使用されることはありません。


質問:準拠しているC#コンパイラーは、の最初の2行を、1つの場所でのみ、つまりコンストラクターへの引数として使用されているCase_2Case_1判断した場合の行に最適化できますか?つまり、のアサーションが失敗する可能性はありますか?unusedLocalVarWeakReferenceCase_2

4

3 に答える 3

12

C#コンパイラが何をするかは問題ではありません。JITter/ GCは、ローカル参照がメソッド本体で機能しなくなった後、それらをクリーンアップすることができます。GC.KeepAliveのドキュメントをご覧ください

また、このパワーポイントのプレゼンテーションは、特にスライド30以降で、JIT/GCが何を達成できるかを説明するのに役立ちます。

于 2010-04-30T07:10:27.270 に答える
3
于 2011-01-08T09:43:07.277 に答える
-1

準拠しているC#コンパイラは、unusedLocalVarが1つの場所でのみ、つまりWeakReferenceコンストラクターへの引数として使用されていることを確認した場合、Case_2の最初の2行をCase_1の行に最適化できますか?

2つの定義は同等であるため、どちらもより効率的であるため、一方から他方への変換は「最適化」ではありません。

つまり、Case_2のアサーションが失敗する可能性はありますか?

はい。本番コンパイラは参照を不必要に保持する可能性が低いため、参照は削除されます。GCはそれをグローバルルートとは見なさず、そのオブジェクトを収集します。

ガベージコレクターは、変数とスコープの観点からプログラムを認識しないことに注意してください。これらの高レベルの概念は、コードがガベージコレクターに到達するまでに長い間コンパイルされてきました。GCは、レジスタ、スレッドスタック、およびグローバル変数のみを認識します。

于 2013-01-06T14:40:29.770 に答える