IList.Add() overwriting existing data [duplicate]
Asked Answered
P

6

6

I'm facing a problem adding data to an IList but the problem is each time I added data the existing data is overwritten with the current one my code is given below:

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);
}

What's the reason behind this?

Pycnidium answered 3/10, 2013 at 10:18 Comment(3)
msdn.microsoft.com/en-us/library/490f96s2.aspxLucrece
the problem you are having as that test is a reference type not a value type, when you add test to the list you are adding a pointer to the memory test sits in, when you then run the next loop you make the changes in that memory space overwriting the data from the previous loop, because of this you need to use the New statment inside the loop to allocate a fresh memory space for that loop to useTonyatonye
its a common error, people make it takes some time to get your head round the idea, think of it like having a filing cabinet, there are 2 ways you can use a filing cabinet you can either put a piece of paper in in with all the data on it (this is Value type) or you can put a piece of paper in with instructions for how to locate the original piece of paper that's stored elsewhere (reference type) in this case you are adding many copies of the piece of paper with instructions on but always making the change on the original sheet the new statement tells it to get you a fresh sheet to useTonyatonye
A
13

move test object creation inside the loop

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);
 }

what you currently doing is updating same instant of test inside the loop and add the same again and again..

Apiculture answered 3/10, 2013 at 10:19 Comment(0)
E
4

You need to move the the creation of Test object to inside the loop. The reason is that the object new Test() is instantiated only once and the reference to the same object keeps getting added to the list in the loop.

Ephraimite answered 3/10, 2013 at 10:19 Comment(0)
G
3

Because Test test is being copied by reference. You need to move it inside the loop.

do it like this

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);
}
Grindstone answered 3/10, 2013 at 10:20 Comment(0)
S
2

Because you don't create new instance in foreach loop, correct the code:

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);
}
Soave answered 3/10, 2013 at 10:20 Comment(0)
S
2

You're using the same reference variable (test) all the time. Try creting new Test() in your loop.

Sputnik answered 3/10, 2013 at 10:20 Comment(0)
S
2

You are creating a single instance of 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
}

And then since you are never creating a new Test instance, you are adding the same reference to the list multiple times. This means that you are essentially just storing the same object over and over: if you make any changes to one item in the list it will immediately be visible in all others because they are essentially the same object

The solution is to move the instantiation of test inside the loop

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);
}

If you need to understand this better, look at reference and value types in .NET and passing by reference/value

Value and Ref types in .NET: http://msdn.microsoft.com/en-us/library/t63sy5hs.aspx

Some info on pointers on Wikipedia http://en.wikipedia.org/wiki/Pointer_(computer_programming)

Strafe answered 3/10, 2013 at 10:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.