0

I am using C#, .Net 4.0, and I want to do the simple task of duplicating an Item in a dictionary (with a different key obviously).

I am running into a few problems.

When I make the initial copy, I have no problems. When I change the value of the copy, the value of the original also changes. Why is this?

private void CopyItem(Guid newItemKey, Guid oldItemKey) { this.dictionary[newItemKey] = this.dictionary[oldItemKey]; this.dictionary[newItemKey].Id = newItemKey; } // this.dictionary[oldItemKey].Id is now equal to newItemKey... Why? 

I have also tried:

private void CopyItem(Guid newItemKey, Guid oldItemKey) { var value = this.dictionary[oldItemKey]; value.Id = newItemKey; this.dictionary[newItemKey] = value; } // this.dictionary[oldItemKey].Id is now equal to newItemKey... Why? 

I still get the same result.

4
  • 2
    Presumably Dictionary holds some reference type. You need to read this. Also this Commented Aug 24, 2015 at 10:53
  • 4
    What is the type of the item? If it is a reference type then you are not making a copy of the item, you are making a copy of the reference, they both reference the same object. Commented Aug 24, 2015 at 10:53
  • 2
    The problem is indeed that both values are just references to the same object. The question I would ask is why do you want to copy stuff anyway? You should almost never want to do this in any program since it's an ugly task that is bound to give you headaches. Most likely, you're thinking of a wrong solution to a problem. Commented Aug 24, 2015 at 11:02
  • Cheers guys hadn't considered that Commented Aug 24, 2015 at 11:26

4 Answers 4

3

You aren't creating a copy. You are using the same item just a different reference to it. In order to copy a reference type you must use the new keyword and set all the properties of the new object to be equal to the old one. If you hold the source code of the reference type you could also implement ICloneable.

Your code should look something like : private void CopyItem(Guid newItemKey, Guid oldItemKey) { // Assuming you implemented ICloneable.. this.dictionary[newItemKey] = this.dictionary[oldItemKey].Clone(); this.dictionary[newItemKey].Id = newItemKey; } 
Sign up to request clarification or add additional context in comments.

Comments

3

This is because if your Dictionary holds a reference type as value, you won't copy the that reference type value but instead you're just re-assigning it. So if you start with a dictionalry like this

[key1][reference_to_0x008B] 

and you copy the dictionary-value to another key, it will just copy the reference itself leading to the following dictionary:

[key1][reference_to_0x008B] [key2][reference_to_0x008B] 

So you'll see the references point to a place in your memory where the same object is located for both keys. Manipulating the object afterwards, you'll get these modifications for both keys afterwards.

In short: The referenced object is NOT cloned automatically, it's just the pointer to it. So you'll have to perform a copy by yourself but this can be very tricky (depending on your needs) - see this article for example.

Comments

1

You'll need to clone the dictionary as the references point to the same memory locations, see the following post for methods to do this.

What is the best way to clone/deep copy a .NET generic Dictionary<string, T>?

Following quote is one of the answers Jon gave

public static Dictionary<TKey, TValue> CloneDictionaryCloningValues<TKey, TValue> (Dictionary<TKey, TValue> original) where TValue : ICloneable { Dictionary<TKey, TValue> ret = new Dictionary<TKey, TValue>(original.Count, original.Comparer); foreach (KeyValuePair<TKey, TValue> entry in original) { ret.Add(entry.Key, (TValue) entry.Value.Clone()); } return ret; } 

Comments

0

Currently when you are copying the object, it is shallow copy, that is the reason,

you should require Deepcopy for reference object (ex. class), you can achieve it by writing your clone function following way.

 public static T DeepCloneCopy<T>(T obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T)formatter.Deserialize(ms); } } 

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.