实例化然后分配vs声明然后分配之间的区别?

时间:2014-02-02 22:15:25

标签: c# .net object heap-memory stack-memory

我的一个朋友问我这个问题。虽然我回答了,但我并不十分相信自己。我寻求的只是满足或纠正。代码段如下:

class Program
{
    static void Main(string[] args)
    {
        DataTable dt1 = new DataTable("Customer");
        dt1.Columns.Add("ID", typeof(int));
        //and some more columns
        dt1.Rows.Add(1);

        *****//what is the difference between doing
        DataTable dt2 = dt1;
        //vs.
        DataTable dt3 = new DataTable();
        dt3 = dt1;*****
    }
}

据我所知,到目前为止,使用new关键字将在堆上创建对象,堆栈上的指针变量和堆栈仅用于简单的数据类型,如int,double等和指针。

根据我的理解,我解释说,dt2将在堆栈上创建,它能够指向堆中的任何DataTable类型,并且我们将dt1分配给{{ 1}},它将指向{0}指向的相同数据表。对于dt3,在堆上创建一个新的数据表对象,dt2将指向它,但当我们dt1时,它开始指向dt3指向的{ {1}}而不是创建的那个。

我不太自信我给出了正确的解释。关于dt3 = dt1的部分。所以我希望社区能够纠正我,或者向我保证我是对的。

2 个答案:

答案 0 :(得分:3)

一般来说,你是对的。在第DataTable dt3 = new DataTable();行中,您创建了一个新的DataTable对象,其中dt3引用指向它。然后,在dt3 = dt1之后你忘了这个对象。 dt3指向先前创建的对象,即:new DataTable("Customer")。您“忘记”的对象可能会被垃圾收集,因为没有对它的引用。

答案 1 :(得分:3)

你基本上是正确的。每个变量dt1dt2dt3都是引用DataTable个对象。当在类类型的变量之间使用赋值运算符时,会发生名为按引用分配的内容。这意味着当您键入dt3 = dt1时,您正在更改dt3以引用完全不同的DataTable对象 - 在这种情况下,DataTable对象dt1指的是。

重要的是要注意,这是类的引用语义的一部分。您正确地注意到在堆栈上分配了“int,double等简单数据类型”。事实上,所有结构都是如此。在c#中,类和结构之间的根本区别在于类具有引用语义,而结构具有值语义

这意味着如果代替class DataTable,您已声明struct DataTable,则会有三个DataTable个对象位于堆栈上,而dt3 = dt1语句将复制DataTable 中的dt1对象按值加入dt3

intbool之类的简单类型实际上是结构体,因此存在于堆栈中并按值复制/传递。

当然,如果没有Eric Lippert的文章"The Stack Is An Implementation Detail"的链接,任何关于价值类型与参考类型的讨论都是不完整的。我已经在这个答案中谈到过“生活在堆栈中”的结构,但这只是为了明白这一点。尝试摆脱将类视为“堆类型”并将结构视为“堆栈类型”的习惯,并开始根据“引用类型”和“值类型”来考虑它们。