-1

I am facing an annoying issue when I am trying to copy an array. The new array keeps a relation even if it's created by .copy() method. Here is the situation,

Main Class

Dictionary<string, string>[] DataCurrentDict = new Dictionary<string, string>[result.Data.Count()];

// 1. Here the DataCurrentDict array is filled with values, having DataCurrentDict[0]["Weight"] = "0.345";
      
ProductData CurrentProductData = new ProductData(DataCurrentDict);

// 2. Here, the CurrentProductData._ProductDataDict[0]["Weight"] = "0.345", GOOD

DataCurrentDict[0]["Weight"] = "1111";

// 3. Here is the problem... After setting a value into DataCurrentDict, the copied array is modified too! So CurrentProductData._ProductDataDict[0]["Weight"] = "1111" ...Why?

ProductData Class

public class ProductData : IDisposable
{
    private Dictionary<string, string>[] _ProductDataDict;

   //CONSTRUCTOR
   public ProductData(Dictionary<string, string>[] ProductDataDict)
   {
       try
       {
           _ProductDataDict = new Dictionary<string, string>[ProductDataDict.Count()];

           Array.Copy(ProductDataDict, _ProductDataDict, ProductDataDict.Length);
       }
       catch (Exception ex) { }
    }
3
  • 1
    Its hard to know what you are trying to achieve, but you do know a copy of a reference type aka reference is still the same reference ? Commented Feb 23, 2021 at 23:00
  • @00110001, so how to copy/clone content into a new independent array? I thought that .copy() method was for that instead of an assignment. Thanks Commented Feb 23, 2021 at 23:05
  • See also stackoverflow.com/questions/198496/… Commented Feb 24, 2021 at 0:18

1 Answer 1

2

You have an array of reference type, copying the array of reference type gives you the same underlying reference identity, it's as simple as that.

You can think of a reference is an address to something, like a post-it-note to something physical in your cupboard, recreating the post-it-note doesn't move the object.

If you want to recreate the reference identity (allocate new memory for your object), aka your dictionarys, there are several solutions.

_ProductDataDict = ProductDataDict
   .Select(x => x.ToDictionary(y => y.Key, y => y.Value))
   .ToArray();

or (likely more efficient)

_ProductDataDict = ProductDataDict
   .Select(x => new Dictionary<string, string>(x))
   .ToArray();

They both recreate the Dictionary, and both loop through each element and add/hash them to the new dictionary

This is an except of the constructor code of dictionary that takes a dictionary

...
Dictionary<TKey, TValue> d = (Dictionary<TKey, TValue>)dictionary;
int count = d._count;
Entry[]? entries = d._entries;
for (int i = 0; i < count; i++)
{
    if (entries![i].next >= -1)
    {
        Add(entries[i].key, entries[i].value);
    }
}

This is an except from ToDictionary

Dictionary<TKey, TElement> d = new Dictionary<TKey, TElement>(capacity, comparer);
foreach (TSource element in source)
{
    d.Add(keySelector(element), elementSelector(element));
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.