IList.Add() перезаписывает существующие данные

Я столкнулся с проблемой добавления данных в IList, но проблема заключается в том, что каждый раз, когда я добавляю данные, существующие данные перезаписываются текущими, мой код приведен ниже:

Test test = new Test();
IList<Test> myList = new List<Test>();

foreach (DataRow dataRow in dataTable.Rows)
{
     test.PatientID = Convert.ToInt64(dataRow.ItemArray[0]);
     test.LastName = dataRow.ItemArray[1].ToString();
     test.FirstName = dataRow.ItemArray[2].ToString();
     myList.Add(test);
}

В чем причина этого?


person Optimus    schedule 03.10.2013    source источник
comment
msdn.microsoft.com/en-us/library/490f96s2.aspx   -  person ta.speot.is    schedule 03.10.2013
comment
проблема, с которой вы столкнулись, поскольку этот тест является ссылочным типом, а не типом значения, когда вы добавляете тест в список, вы добавляете указатель на тест памяти, в котором находится тест памяти, когда вы затем запускаете следующий цикл, вы вносите изменения в эту память пространство, перезаписывающее данные из предыдущего цикла, из-за этого вам нужно использовать новый статус внутри цикла, чтобы выделить новое пространство памяти для использования этого цикла.   -  person MikeT    schedule 03.10.2013
comment
Всем спасибо, что указали на мою ошибку :)   -  person Optimus    schedule 03.10.2013
comment
это распространенная ошибка, людям требуется некоторое время, чтобы обдумать идею, подумайте об этом как о шкафе для документов, есть 2 способа использования шкафа для документов: вы можете либо положить лист бумаги со всеми данные на нем (это тип значения) или вы можете вставить лист бумаги с инструкциями о том, как найти исходный лист бумаги, который хранится в другом месте (тип ссылки) в этом случае вы добавляете много копий листа бумаги с инструкциями, но всегда внося изменения в исходный лист, новый оператор говорит ему, чтобы вы использовали новый лист для использования   -  person MikeT    schedule 03.10.2013


Ответы (6)


переместить создание тестового объекта внутрь цикла

IList<Test> myList = new List<Test>();

foreach (DataRow dataRow in dataTable.Rows)
{   Test test =new Test();
    test.PatientID = Convert.ToInt64(dataRow.ItemArray[0]);
    test.LastName = dataRow.ItemArray[1].ToString();
    test.FirstName = dataRow.ItemArray[2].ToString();
    myList.Add(test);
 }

то, что вы сейчас делаете, это обновление одного и того же момента test внутри цикла и добавление одного и того же снова и снова..

person Damith    schedule 03.10.2013

Вам нужно переместить создание тестового объекта внутрь цикла. Причина в том, что экземпляр объекта new Test() создается только один раз, а ссылка на тот же объект продолжает добавляться в список в цикле.

person hawk    schedule 03.10.2013

Потому что Test test копируется по ссылке. Вам нужно переместить его внутри цикла.

сделай это так

IList<Test> myList = new List<Test>();
foreach (DataRow dataRow in dataTable.Rows)
{
     Test test =new Test();
     test.PatientID = Convert.ToInt64(dataRow.ItemArray[0]);
     test.LastName = dataRow.ItemArray[1].ToString();
     test.FirstName = dataRow.ItemArray[2].ToString();
     myList.Add(test);
}
person Ehsan    schedule 03.10.2013

Поскольку вы не создаете новый экземпляр в цикле foreach, исправьте код:

Test test = null;
IList<Test> myList = new List<Test>();

foreach (DataRow dataRow in dataTable.Rows)
{
   test = new Test();
   test.PatientID = Convert.ToInt64(dataRow.ItemArray[0]);
   test.LastName = dataRow.ItemArray[1].ToString();
   test.FirstName = dataRow.ItemArray[2].ToString();
   myList.Add(test);
}
person Snake Eyes    schedule 03.10.2013

Вы все время используете одну и ту же ссылочную переменную (тест). Попробуйте создать новый Test() в своем цикле.

person borkovski    schedule 03.10.2013

Вы создаете один экземпляр Test

Test test = new Test(); // This is your instance
IList<Test> myList = new List<Test>();

foreach (DataRow dataRow in dataTable.Rows)
{
    // Here you change the values of the existing instance each time you loop
    test.PatientID = Convert.ToInt64(dataRow.ItemArray[0]);
    test.LastName = dataRow.ItemArray[1].ToString();
    test.FirstName = dataRow.ItemArray[2].ToString();
    myList.Add(test); // but you are still just adding the same reference to the list multiple times
}

И затем, поскольку вы никогда не создаете новый экземпляр Test, вы добавляете одну и ту же ссылку в список несколько раз. Это означает, что вы, по сути, просто сохраняете один и тот же объект снова и снова: если вы внесете какие-либо изменения в один элемент в списке, он будет немедленно виден во всех других, потому что они по сути являются одним и тем же объектом.

Решение состоит в том, чтобы переместить экземпляр теста внутрь цикла.

IList<Test> myList = new List<Test>();

foreach (DataRow dataRow in dataTable.Rows)
{
    Test test = new Test(); // Each loop iteration will now create a new instance of Test
    test.PatientID = Convert.ToInt64(dataRow.ItemArray[0]);
    test.LastName = dataRow.ItemArray[1].ToString();
    test.FirstName = dataRow.ItemArray[2].ToString();
    myList.Add(test);
}

Если вам нужно лучше понять это, посмотрите на типы ссылок и значений в .NET и передачу по ссылке/значению.

Типы значений и ссылок в .NET: http://msdn.microsoft.com/en-us/library/t63sy5hs.aspx

Некоторая информация об указателях в Википедии http://en.wikipedia.org/wiki/Pointer_(computer_programming)

person Charleh    schedule 03.10.2013