2017-04-08 2 views
2

は、私は私の場合には、この .NETは実行時に「無関係な」コードを検出し、その中のオブジェクトをガベージコレクトできますか?

public void foo(){ 
    Object very_large_object; 
    if (very_large_object.some_runtime_condition()) { 
     do_something(); 
     return; 
    } 
    do_something_else (very_large_object); 
} 

のようなC#の方法は、do_somethingは高価な方法であり、完了するまでに時間がかかる場合があり持っていると仮定します。実行中は、do_something_elseが呼び出されないので、very_larget_objectは不要になり、ガベージコレクトすることができますか?

+0

very_large_objectのみをインスタンス化するにはどうすればよいですか?if節は必要な場合にインスタンス化しますか? –

+0

@GianPaolo私は私のコードを単純化したようです...条件は実際には 'very_large_object'に依存します。しかし、私はそれをnullに設定して安全にするべきだと思います。 – sqd

答えて

1

はいできます。オブジェクトの存続期間が何らかの形で囲みスコープに関連しているという誤解はよくあります(たとえば、fooスコープが終了した場合にのみvery_large_objectを収集することができます)。あなたは、簡単なアプリケーションを使用して、特定のケースを確認することができます。

class Program {   
    static void Main() { 
     var o = new TestObject(); 
     var test = Console.ReadKey(); 
     if (test.Key == ConsoleKey.Enter) { 
      DoSomething();    
      Console.ReadKey(); 
      return; 
     } 
     DoSomethingElse(o); 
    } 

    static void DoSomething() { 
     Console.WriteLine("doing something"); 
     Thread.Sleep(500); 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     Console.WriteLine("GC ran"); 
    } 

    static void DoSomethingElse(TestObject o) { 
     Console.WriteLine(o); 
    } 
} 

public class TestObject { 
    public TestObject() { 

    } 
    ~TestObject() { 
     Console.WriteLine("finalizer running"); 
    } 
} 

あなたが最適化とリリースモードで有効になっていることをコンパイルした場合(コンソールでEnterキーを押した後)、それは出力は次のようになります。

doing something 
finalizer running 
GC ran 

ので、 oはゴミとみなされ、私たちがまだDoSomethingメソッドの中にいる間にファイナライザキューに入れられたことは明らかです。オプティマイザは、DoSomethingElseでブランチを投げ捨てることはできませんでした。なぜなら、実行するかどうかはコンソール入力に依存するからです。 returnを削除した場合は、もちろん収集されません。

関連する問題