отличается от вопроса с помощью простого =

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?

Теги:
datatable
reference
pass-by-reference

2 ответа

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 является ссылочным типом. Спасибо за эту информацию, это все объясняет! Обратите внимание, что в базе данных уже есть метод копирования.
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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню