отличается от вопроса с помощью простого =
-
06-07-2019 - |
Вопрос
У меня есть вариант ответа на вопрос. Я знаю все о вызовах с 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();
Итак, мой вопрос: что заставляет datatable работать иначе, чем простое целочисленное поле. Почему создается ссылка, когда я использую mVar4 = mVar3 вместо другой копии DataTable?
Решение
Вы столкнулись с разницей между ссылочным типом и типом значения. Р>
Вот статья msdn о различиях . р>
Более наглядным ответом будет то, что оба фактически выполняют одну и ту же операцию, различие состоит в том, что в первом примере (два целых числа) назначение mVar2 = mVar1 присваивает значение mVar1 mVar2, которое равно 1. Однако в случае DataTable фактически назначается область памяти, а не DataTable.
Скажем, например, что созданная вами DataTable находится в ячейке памяти 20. Это будет означать, что ссылка mVar1 будет содержать ссылку на эту ячейку (20). Когда вы выполняете присваивание mVar2 = mVar1, вы говорите mVar2 хранить то же значение, что и mVar1, поэтому mVar2 также ссылается на ячейку памяти 20. В результате обе переменные ссылаются на одну и ту же таблицу данных.
Чтобы описать поведение, которое вы описываете, вам, как вы заявили, действительно нужно иметь возможность копирования. Пришлось бы выделить совершенно новый объект и скопировать состояние предыдущего объекта в новый.
Для класса 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;
}
Другие советы
Вызов 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.