2016-11-19 56 views
4

我有這樣的課。 (這只是例子)構造函數拋出的異常以及實例和內存分配會發生什麼?

public class NewTest 
    { 
     public int I { get; set; } 
     public NewTest() 
     {     
      I = 10; 
      throw new ApplicationException("Not Possible"); 
     } 
    } 

現在,如果我使用類這樣

NewTest t = new NewTest(); 

在上面行NewTest構造函數拋出異常變量t從未指定任何值constuctor之前得到完成它拋出異常,但根據測試以及每個其他問題(Why throwing exception in constructor results in a null reference?)創建對象。

現在這個對象是在堆中創建的,但它不包含任何根變量作爲引用,所以它會爲垃圾收集創建問題?或者是內存泄漏的東西?


下面的例子幫助我清除了我的困惑。 另一個實施例

namespace ConsoleApplication1 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     NewMethod(); 
     System.GC.Collect(); 
     Console.WriteLine("Completed"); 
     Console.ReadLine(); 
    } 

    private static void NewMethod() 
    { 
     Object obj = null; 
     try 
     { 
      Console.WriteLine("Press any key to continue"); 
      Console.ReadLine(); 
      NewTest t = new NewTest(out obj); 
     } 
     catch 
     { 
      Console.WriteLine("Exception thrown"); 
     } 

     try 
     { 
      Console.WriteLine("Press any key to continue"); 
      Console.ReadLine(); 
      NewTest1 t = new NewTest1(); 
     } 
     catch 
     { 
      Console.WriteLine("Exception thrown"); 
     } 

     Console.WriteLine("Press any key to continue"); 
     Console.ReadLine(); 

     System.GC.Collect(); 

     Console.WriteLine("Press any key to continue"); 
     Console.ReadLine();   

    } 
} 

public class NewTest1 
{ 
    public int I { get; set; } 
    public NewTest1() 
    { 
     I = 10; 
     throw new ApplicationException("Not Possible"); 
    } 
} 

public class NewTest 
{ 
    public int I { get; set; } 
    public NewTest(out Object obj) 
    { 
     obj = this; 
     I = 10; 
     throw new ApplicationException("Not Possible"); 
    } 
    } 
} 
+1

GC確實喜歡沒有被引用的對象。對於所有它關心,它認爲這是你可以寫的最有效的代碼:)好吧,現在不計算它也必須收集異常對象。你在這裏煩惱一個不存在的問題。 –

回答

3

在構造拋出異常不是垃圾收集器的問題,並且絕對不導致內存泄漏。

儘管從堆中分配的內存永遠不會將其發送到您的程序,但它可用於運算符new的內部實現,該操作符負責確保新創建的實例符合垃圾回收的條件。

+1

我接受了答案。即使我通過windbg獲得證據,我也會發布相關示例,以便有助於理解問題。 – dotnetstep

1

如果你看起來邏輯上是空值只是你的參考值可能有的值。您的代碼等於

NewTest t = null; 
t = new NewTest();-> the assignment never occurs because you throw exception 

因此,此引用的值爲null,垃圾回收器沒有問題。

+0

我知道變量t沒有問題,但對象實際上分配了內存,所以內存得到指示,因爲沒有根。 – dotnetstep

6

其他答案是正確的;我將給他們添加一個有趣的事實,即其構造函數拋出的可終結對象仍然是最終確定的。這意味着終結器可以對構造函數沒有正常完成的對象進行操作。 終結器不能假定對象在最終確定時被初始化。這又是一個很長的原因,爲什麼很難寫出正確的終結者。

+0

是的。我同意你@Eric Lippert。你對終結者的觀點也是有效的,但我想我會在某一天嘗試。感謝您的專家評論。我應該允許多次投票。 – dotnetstep

相關問題