2009-06-23 4 views
2

У меня есть вариант по вопросу ref. Я знаю все о вызове с помощью ref или наших параметров и как он влияет на переменные и их значения. У меня была эта проблема с DataTable, и я хочу знать, почему datatable отличается от простой целочисленной переменной.другой вопрос вопрос используя простой =

У меня есть физический ответ о том, как исправить проблему, но я хочу знать, почему она работает так, как она делает.

Если вы используете простые переменные это то, что я ожидал

 int mVar1 = 1; 
     int mVar2 =1; 

     mVar2 = mVar1; 

     mVar2 = 5; 

     Console.WriteLine(mVar1.ToString()); 
     Console.WriteLine(mVar2.ToString()); 

отображает 1,5 в консоли.

НО если вы делаете то же самое с DataTable он делает ссылку на первый 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?

ответ

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; 
} 
+0

Мне нравится статья MSDN как он объясняет, что-то типа. И теперь я вижу, что, когда я нависаю над типом данных DataTable в visual studio, он говорит, что класс DataTable, который согласно статье MSDN является ссылочным типом. Благодарим вас за эту информацию, это все объясняет! Обратите внимание, что у datatable уже есть метод копирования. –

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 = новый DataTable(); изменяет ссылку в местоположении mVar4, она не изменяет объект, на который ссылается mVar4.

Смежные вопросы