构造函数的异常抛出以及实例和内存分配会发生什么?

时间:2016-11-19 11:51:55

标签: c# garbage-collection

我有这样的课。 (这只是示例)

    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?)创建对象。

现在这个对象是在Heap中创建的,但是它不包含任何根变量以供参考,所以它是否会为垃圾收集创建问题?或是内存泄漏了什么?

以下示例帮我清除了我的困惑。 另一个例子

 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");
    }
  }
 }

3 个答案:

答案 0 :(得分:8)

其他答案是正确的;我将向他们添加一个有趣的事实,即最终化的对象,其构造函数抛出仍然是最终的。这意味着终结器可以对构造函数未正常完成的对象进行操作。 终结器不能假定对象在完成时初始化。这是为什么很难写出正确的终结器的另一个原因。

答案 1 :(得分:3)

在构造函数中抛出异常对垃圾收集器来说不是问题,它肯定不会导致内存泄漏。

虽然从堆中分配的内存永远不会进入您的程序,但它可用于运算符new的内部实现,它负责确保新创建的实例符合垃圾回收条件。< / p>

答案 2 :(得分:1)

如果从逻辑上看,null只是您的引用可能具有的值。您的代码等于

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

因此,此引用的值为null,对于垃圾收集器没有问题。