我的一个朋友问我这个问题。虽然我回答了,但我并不十分相信自己。我寻求的只是满足或纠正。代码段如下:
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
的部分。所以我希望社区能够纠正我,或者向我保证我是对的。
答案 0 :(得分:3)
一般来说,你是对的。在第DataTable dt3 = new DataTable();
行中,您创建了一个新的DataTable
对象,其中dt3
引用指向它。然后,在dt3 = dt1
之后你忘了这个对象。 dt3
指向先前创建的对象,即:new DataTable("Customer")
。您“忘记”的对象可能会被垃圾收集,因为没有对它的引用。
答案 1 :(得分:3)
你基本上是正确的。每个变量dt1
,dt2
和dt3
都是引用到DataTable
个对象。当在类类型的变量之间使用赋值运算符时,会发生名为按引用分配的内容。这意味着当您键入dt3 = dt1
时,您正在更改dt3
以引用完全不同的DataTable
对象 - 在这种情况下,DataTable
对象dt1
指的是。
重要的是要注意,这是类的引用语义的一部分。您正确地注意到在堆栈上分配了“int,double等简单数据类型”。事实上,所有结构都是如此。在c#中,类和结构之间的根本区别在于类具有引用语义,而结构具有值语义。
这意味着如果代替class DataTable
,您已声明struct DataTable
,则会有三个DataTable
个对象位于堆栈上,而dt3 = dt1
语句将复制DataTable
中的dt1
对象按值加入dt3
。
int
和bool
之类的简单类型实际上是结构体,因此存在于堆栈中并按值复制/传递。
当然,如果没有Eric Lippert的文章"The Stack Is An Implementation Detail"的链接,任何关于价值类型与参考类型的讨论都是不完整的。我已经在这个答案中谈到过“生活在堆栈中”的结构,但这只是为了明白这一点。尝试摆脱将类视为“堆类型”并将结构视为“堆栈类型”的习惯,并开始根据“引用类型”和“值类型”来考虑它们。