Access to a property of a collection of structures from another collection

I have a structure that I need to store in a collection. The structure has a property that returns a dictionary.

public struct Item { private IDictionary<string, string> values; public IDictionary<string, string> Values { get { return this.values ?? (this.values = new Dictionary<string, string>()); } } } public class ItemCollection : Collection<Item> {} 

When testing, I found that if I add an item to the collection and then try to access the dictionary, the structs values ​​property will never be updated.

  var collection = new ItemCollection { new Item() }; // pre-loaded with an item collection[0].Values.Add("myKey", "myValue"); Trace.WriteLine(collection[0].Values["myKey"]); // KeyNotFoundException here 

However, if I first load an item and then add it to the collection, the value field is saved.

  var collection = new ItemCollection(); var item = new Item(); item.Values.Add("myKey", "myValue"); collection.Add(item); Trace.WriteLine(collection[0].Values["myKey"]); // ok 

I have already decided that the structure is the wrong option for this type, and when using the class the problem does not arise, but I am curious that the other is between these two methods. Can anyone explain what is happening?

+4
source share
3 answers

As mentioned earlier, change the struct Item to class Item . When you use a struct , the collection[0] expression does not return a reference to the object created in new ItemCollection { new Item() } , but rather creates a copy of it and passes it to you.

+1
source

Instead, change the structure as a class:

 public class Item {} 

Now I am not familiar with internals, but structure is a value type, and a class is a reference type, and I believe that there is logic there that explains why you get an exception when you run the first code example.

I hope someone can intervene to give you a more detailed answer, but for now just change the structure to a class.

+2
source

"Item" is an element of value. this means that if you access the collection, a copy is made. all operations are performed on this copy

  collection[0].Values.Add("myKey", "myValue"); 

here, a copy is created from the first element, then Access get Access creates a new instance, which is stored in the copy, and then the element is added. then the copy will be destroyed.

workaround will create a dictionary of values ​​directly when creating the structure

 public struct Item { private IDictionary<string, string> values = new Dictionary<string, string>(); public IDictionary<string, string> Values { get { return this.values; } } } 

if you access the collection, a copy is made. but this copy contains a link to the same dictionary of values ​​as the original. therefore the source dictionary is changed

+1
source

Source: https://habr.com/ru/post/1435016/


All Articles