我有一个关于by ref问题的变体。我知道调用ref或我们的参数以及它如何影响变量及其值。我有一个DataTable的问题,我想知道为什么数据表与简单的整数变量不同。
我对如何解决问题有实际的答案,但我想知道它为何如此有效。
如果您使用简单变量,它就会达到我的预期
int mVar1 = 1;
int mVar2 =1;
mVar2 = mVar1;
mVar2 = 5;
Console.WriteLine(mVar1.ToString());
Console.WriteLine(mVar2.ToString());
显示 1,5 在控制台中。
但如果你对DataTable做同样的事情,它会引用第一个数据表而不是新值:
DataTable mVar3 = new DataTable();
DataTable mVar4 = new DataTable();
// Create DataColumn objects of data types.
DataColumn colString = new DataColumn("StringCol");
colString.DataType = System.Type.GetType("System.String");
mVar3.Columns.Add(colString);
// Create DataColumn objects of data types.
DataColumn colString2 = new DataColumn("StringCol123");
colString2.DataType = System.Type.GetType("System.String");
mVar4.Columns.Add(colString2);
foreach (DataColumn tCol in mVar3.Columns)
{
Console.WriteLine(tCol.ColumnName);
}
foreach (DataColumn tCol in mVar4.Columns)
{
Console.WriteLine(tCol.ColumnName);
}
mVar4 = mVar3;
//change mVar4 somehow and see if mVar3 changes
foreach (DataColumn tCol in mVar4.Columns)
{
tCol.ColumnName = "Test";
}
foreach (DataColumn tCol in mVar3.Columns)
{
Console.WriteLine(tCol.ColumnName);
}
foreach (DataColumn tCol in mVar4.Columns)
{
Console.WriteLine(tCol.ColumnName);
}
控制台显示: StringCol StringCol123 测试 测试
通过说mVar4 = mVar3,它会导致mVar4成为对mVar3的引用。
解决这个问题的方法是
DataTable mVar4 = mVar3.Copy();
所以我的问题是:是什么导致数据表的执行方式与简单的整数字段不同。当我使用mVar4 = mVar3而不是DataTable的不同副本时,为什么会创建引用?
答案 0 :(得分:2)
您正在遇到引用类型和值类型之间的差异。
这是关于差异的msdn article。
更具描述性的答案是两者实际上都在执行相同的操作,不同之处在于,在第一个示例(两个整数)中,mVar2 = mVar1的赋值将mVar1的值赋给mVar2,即1。但是,对于DataTable,实际分配的是内存位置,而不是DataTable。
例如,假设您创建的DataTable驻留在内存位置20.这意味着引用mVar1将保存对该位置的引用(20)。当您执行赋值mVar2 = mVar1时,您告诉mVar2保持与mVar1相同的值,因此mVar2也会引用内存位置20。结果是两个变量都引用了相同的DataTable。
为了实现您所描述的行为,您确实需要具备复制功能,如您所述。它必须分配一个全新的对象,并将前一个对象的状态复制到新对象。
对于DataTable类,您可以在扩展方法中将其扩展为:
public static DataTable Copy(this DatTable original)
{
var result = new DataTable();
//assume Property1 was a property of a DataTable
result.Property1 = original.Property1;
//continue copying state from original to result
return result;
}
答案 1 :(得分:0)
呼叫mVar2 = mVar1;复制存储在mVar1位置的值。在这种情况下,这意味着1将复制到位置mVar2中。在第二种情况下,存储在mVar3中的值再次被复制到mVar4的位置。但是,在这种情况下,因为DataTable是引用类型,所以复制的值是对实际DataTable对象的引用。
要进一步显示,请将以下内容添加到您发布的代码的末尾:
mVar4 = new DataTable();
// Create DataColumn objects of data types.
DataColumn colString3 = new DataColumn("StringCol1234");
colString2.DataType = System.Type.GetType("System.String");
mVar4.Columns.Add(colString3);
foreach (DataColumn tCol in mVar3.Columns)
{
Console.WriteLine(tCol.ColumnName); // still outputs test
}
foreach (DataColumn tCol in mVar4.Columns)
{
Console.WriteLine(tCol.ColumnName); // now outputs StringCol1234
}
如果您再次将mVar4设置为DataTable的新实例,则更改不会反映在mVar3中。这是因为调用mVar4 = new DataTable();更改mVar4位置的引用,它不会更改mVar4引用的对象。