tags:

views:

961

answers:

6
Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<    SaleItem>> ();

saleItems = new List <SaleItem> ();

saleItemNew.Add("1", saleItems);

At this point the list in the Dictionary has values.

saleItems.Clear();

However, when I clear out the list previously assigned to it, the dictionary's value List is now empty...why?

+2  A: 

The reason is that Dictionary is a reference and not a value type. When you assign a Dictionary to another variable it does not perform a deep copy. Instead it just points another reference at the same object. Since there is only one object, clearing via either reference will be visible to both references.

This in contrast to value types in the .Net Framework. Assignment of a value type essentially performs a shallow copy of the data and creates two independent objects. Note, that if the value type has a reference field, the two field in the two value types will still point to the same object.

JaredPar
+10  A: 

The dictionary contains the same reference to the list, so modifying the list will change both references.

Microsoft documentation about reference types: http://msdn.microsoft.com/en-us/library/490f96s2.aspx

John JJ Curtis
I'm assuming that lists are the same way?
Dano
Yes, they are. Anyone who modifies the reference modifies it for everyone who uses the reference. Think of the reference as nothing more than a pointer to the underlying list.
John JJ Curtis
Speaking of which, if you want to add lots of Lists that don't share the same reference, just do "new List<SaleItem>()" and add that to the dictionary each time you need a new list.
John JJ Curtis
+2  A: 

it has to do with memory usage and pointers. You have a stack, and a heap when allocating memory for objects, that memory is one the heap. Your saleItems variable is defined on the stack and points to the memory address on the heap. Your Dictionary is also on the stack pointing at the heap.

when you say:

saleItems = new List<SaleItem>()

the variable saleItems is pushed onto the stack and contains a memory address the points to the location of the data on the heap. Lets say 0x0100. Now you add a new DictionaryItem to your dictionary. The DictionaryItem is placed on the heap with two properties, Key and Value. In this case, you have added saleItems as Value, so Value has the address 0x0100 as well. Now DictionaryItem.Value is pointing at the same memory as saleItems. When you call saleItems.Clear, you are saying find the list at address 0x0100 and remove all items. So the dictionary and the variable both become empty because they are pointing at the same memory. What you want to do is say saleItems = new List<SaleItem>(); again. Now saleItems will point to a new address on the heap (say 0x0200). DictionaryItem.Value is still pointing at memory address 0x0100 so you can act on the saleItems variable without affecting the data in your dictionary.

For more information on stacks and heaps in c# try this article: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91

NerdFury
These are implementation details. The salient point here is "value type" versus "reference type", not the details of how they might be implemented internally.
Jason
IMO - 'value type' and 'reference type' monikers are meaningless unless you understand how the underlying memory is used, and that requires understanding the stack and heap and their relationship. Classes, Delegates, etc are reference types, but what does it mean to be a reference type. It means that memory on the stack is used to reference a memory address in the heap. Ints, bools, enumerations are value types, but what does that mean? It means that memory is used on the stack to store a true value. IMO this is vital to understand.
NerdFury
A: 

Adding the List to the dictionary is just a shallow copy... A new list with the same values is not created and added (a deep copy); rather a reference to the old list is added.

Polaris878
A: 

It uses the same reference.

A better way to do it is

Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<SaleItem>>();
saleItemNew.Add("1", new List<SaleItem>());

And for clearing

saleItemNew["1"] = new List<SaleItem>();
Yahya
A: 

Is there any workaround for this? ToArray() or something! or is there an alternative construct?

learnerplates