2

My initial intention is to send list asynchronously through a TCP Stream. But directly after passing the list to the asynchronous thread I need to clear it to fill it again with new data. So I used Shallow cloning to create a copy of the list, and pass it to the background thread:

private List<MyDataObject> GetShallowCloneOfDataList(List<MyDataObject> dataEvents)
{
    return new List<MyDataObject>(dataEvents);
}

and here is my final code:

List<MyDataObject> data = new List<MyDataObject>();
while(hasMoreData)
{
    data.clear(); 
    FillListFromServer(data);
    List<MyDataObject> clonedList = GetShallowCloneOfDataList(data);
    Task.Run(() => SendDataList(clonedList));
}

My question is, when I clear the original list data, will the items inside the cloned list be also affected? Testing my code revealed that they are not affected, but I am not sure if this will remain true when handling large amounts of data (200K per second).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Hassan Mokdad
  • 5,832
  • 18
  • 55
  • 90
  • Read what is reference types – mybirthname Sep 26 '16 at 05:58
  • Apart from your question (which is answered below), why pass a clone of the list to SendDataList and then clear your own list? Why not pass the original list to the function, don't touch this original list anymore and fill a new list? Much more efficient isn't it? – Harald Coppoolse Sep 26 '16 at 06:40
  • @HaraldCoppoolse, yes indeed this is more efficient, but unfortunately the situation is much more complicated than the code snippet i showed above. The original list is hooked on the start of the application to an observer class that will fill it with new data upon events pushed from a data server, So creating a new list is not an option :( – Hassan Mokdad Sep 26 '16 at 07:18

2 Answers2

4

No, the existing items aren't affected, other than being potentially eligible for garbage collection.

This is just like setting a variable to null, effectively:

MyDataObject x = new MyDataObject(); // And populate
MyDataObject y = x; // Just copy the reference
x = null; // This doesn't change either y or the data in the object

Another way of thinking about it is if you had an addressbook full of your friends and family's addresses, and then threw it on the fire... you wouldn't be able to find out where your friends and family were any more, but it wouldn't change where they lived. (See this answer for more on this kind of analogy.)

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • So I can safely assume that all the original items are still in the cloned list after i clear the original one? And i will not loose data when sending? – Hassan Mokdad Sep 26 '16 at 05:59
  • 1
    @HassanMokdad: Yes, indeed. You have two independent collections which happen to refer to the same objects - like two addressbooks which happen to have the same set of addresses in. Erasing all the addresses out of one of them doesn't modify the houses or the other addressbook. – Jon Skeet Sep 26 '16 at 06:54
  • Thanks for the nice example :) – Hassan Mokdad Sep 26 '16 at 07:18
1

So let's think about it this way. You have objects in memory, and you have a list where each index references one of these objects in memory.

You decided to create a new list that reference the same objects at the same index, which is the reference of List1 at index 0 is the same as the reference of List2 at index 0.

Now you cleared the first list (which doesn't even know about the existence of the second list). Your second list remains intact ! The number of items doesn't make a difference here.

The only thing that you need to care about is that if MyDataObject is a class and not a struct, then changing the properties of on item in a list changes it in the other. Example:

data[0].Foo = 12;
Console.WriteLine(clonedList[0].Foo); // prints 12

But you don't seem to do this in the shown code. Pointing that out just in case you faced it in the future.

Zein Makki
  • 29,485
  • 6
  • 52
  • 63