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

Viewed 240752

I've got a generic dictionary Dictionary<string, T> that I would like to essentially make a Clone() of ..any suggestions.

14 Answers

(Note: although the cloning version is potentially useful, for a simple shallow copy the constructor I mention in the other post is a better option.)

How deep do you want the copy to be, and what version of .NET are you using? I suspect that a LINQ call to ToDictionary, specifying both the key and element selector, will be the easiest way to go if you're using .NET 3.5.

For instance, if you don't mind the value being a shallow clone:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
                                               entry => entry.Value);

If you've already constrained T to implement ICloneable:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, 
                                               entry => (T) entry.Value.Clone());

(Those are untested, but should work.)

Okay, the .NET 2.0 answers:

If you don't need to clone the values, you can use the constructor overload to Dictionary which takes an existing IDictionary. (You can specify the comparer as the existing dictionary's comparer, too.)

If you do need to clone the values, you can use something like this:

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;
}

That relies on TValue.Clone() being a suitably deep clone as well, of course.

That's what helped me, when I was trying to deep copy a Dictionary < string, string >

Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);

Good luck

For .NET 2.0 you could implement a class which inherits from Dictionary and implements ICloneable.

public class CloneableDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : ICloneable
{
    public IDictionary<TKey, TValue> Clone()
    {
        CloneableDictionary<TKey, TValue> clone = new CloneableDictionary<TKey, TValue>();

        foreach (KeyValuePair<TKey, TValue> pair in this)
        {
            clone.Add(pair.Key, (TValue)pair.Value.Clone());
        }

        return clone;
    }
}

You can then clone the dictionary simply by calling the Clone method. Of course this implementation requires that the value type of the dictionary implements ICloneable, but otherwise a generic implementation isn't practical at all.

You could always use serialization. You could serialize the object then deserialize it. That will give you a deep copy of the Dictionary and all the items inside of it. Now you can create a deep copy of any object that is marked as [Serializable] without writing any special code.

Here are two methods that will use Binary Serialization. If you use these methods you simply call

object deepcopy = FromBinary(ToBinary(yourDictionary));

public Byte[] ToBinary()
{
  MemoryStream ms = null;
  Byte[] byteArray = null;
  try
  {
    BinaryFormatter serializer = new BinaryFormatter();
    ms = new MemoryStream();
    serializer.Serialize(ms, this);
    byteArray = ms.ToArray();
  }
  catch (Exception unexpected)
  {
    Trace.Fail(unexpected.Message);
    throw;
  }
  finally
  {
    if (ms != null)
      ms.Close();
  }
  return byteArray;
}

public object FromBinary(Byte[] buffer)
{
  MemoryStream ms = null;
  object deserializedObject = null;

  try
  {
    BinaryFormatter serializer = new BinaryFormatter();
    ms = new MemoryStream();
    ms.Write(buffer, 0, buffer.Length);
    ms.Position = 0;
    deserializedObject = serializer.Deserialize(ms);
  }
  finally
  {
    if (ms != null)
      ms.Close();
  }
  return deserializedObject;
}

In the case you have a Dictionary of "object" and object can be anything like (double, int, ... or ComplexClass):

Dictionary<string, object> dictSrc { get; set; }

public class ComplexClass : ICloneable
{
    
    private Point3D ...;
    private Vector3D ....;
    [...]

    public object Clone()
    {
        ComplexClass clone = new ComplexClass();
        clone = (ComplexClass)this.MemberwiseClone();
        return clone;
    }

}


dictSrc["toto"] = new ComplexClass()
dictSrc["tata"] = 12.3
...

dictDest = dictSrc.ToDictionary(entry => entry.Key,
                                entry => ((entry.Value is ICloneable) ? (entry.Value as ICloneable).Clone() : entry.Value) );


Here is some real "true deep copying" without knowing type with some recursive walk, good for the beginnig. It is good for nested types and almost any tricky type I think. I did not added nested arrays handling yet, but you can modify it by your choice.

Dictionary<string, Dictionary<string, dynamic>> buildInfoDict =
    new Dictionary<string, Dictionary<string, dynamic>>()
    {
        {"tag",new Dictionary<string,dynamic>(){
                 { "attrName", "tag"  },
                 { "isCss", "False"  },
               { "turnedOn","True" },
                 { "tag",null }
            } },
        {"id",new Dictionary<string,dynamic>(){
                 { "attrName", "id"  },
                 { "isCss", "False"  },
               { "turnedOn","True" },
                 { "id",null }
            } },
                {"width",new Dictionary<string,dynamic>(){
                 { "attrName", "width"  },
                 { "isCss", "True"  },
               { "turnedOn","True" },
                 { "width","20%" }
            } },
                {"height",new Dictionary<string,dynamic>(){
                 { "attrName", "height"  },
                 { "isCss", "True"  },
               { "turnedOn","True" },
                 { "height","20%" }
            } },
                {"text",new Dictionary<string,dynamic>(){
                 { "attrName", null  },
                 { "isCss", "False"  },
               { "turnedOn","True" },
                 { "text","" }
            } },
                {"href",new Dictionary<string,dynamic>(){
                 { "attrName", null  },
                 { "isCss", "False"  },
                 { "flags", "removeAttrIfTurnedOff"  },
               { "turnedOn","True" },
                 { "href","about:blank" }
            } }
    };

var cln=clone(buildInfoDict);

public static dynamic clone(dynamic obj)
{
    dynamic cloneObj = null;
    if (IsAssignableFrom(obj, typeof(IDictionary)))
    {
        cloneObj = Activator.CreateInstance(obj.GetType());
        foreach (var key in obj.Keys)
        {
            cloneObj[key] = clone(obj[key]);
        }

    }
    else if (IsNumber(obj) || obj.GetType() == typeof(string))
    {
        cloneObj = obj;
    }
    else
    {
        Debugger.Break();
    }
    return cloneObj;
}


public static bool IsAssignableFrom(this object obj, Type ObjType = null, Type ListType = null, bool HandleBaseTypes = false)
{
    if (ObjType == null)
    {
        ObjType = obj.GetType();
    }

    bool Res;

    do
    {
        Res = (ObjType.IsGenericType && ObjType.GetGenericTypeDefinition().IsAssignableFrom(ListType)) ||
            (ListType == null && ObjType.IsAssignableFrom(obj.GetType()));
        ObjType = ObjType.BaseType;
    } while ((!Res && ObjType != null) && HandleBaseTypes && ObjType != typeof(object));

    return Res;
}

public static bool IsNumber(this object value)
{
    return value is sbyte
            || value is byte
            || value is short
            || value is ushort
            || value is int
            || value is uint
            || value is long
            || value is ulong
            || value is float
            || value is double
            || value is decimal;
}

Here is another way to clone a dictionary, assuming you know to do the "right" thing as far as handling whatever is hiding behind the "T" (a.k.a. "object") in your specific circumstances.

internal static Dictionary<string, object> Clone(Dictionary<string, object> dictIn) 
    {
        Dictionary<string, object> dictOut = new Dictionary<string, object>();
    
        IDictionaryEnumerator enumMyDictionary = dictIn.GetEnumerator();
        while (enumMyDictionary.MoveNext())
        {
            string strKey = (string)enumMyDictionary.Key;
            object oValue = enumMyDictionary.Value;
            dictOut.Add(strKey, oValue);
        }
    
        return dictOut; 
    }

I would evaluate if T was a value or reference type. In the case T was a value type I would use the constructor of Dictionary, and in the case when T was a reference type I would make sure T inherited from ICloneable.

It will give

    private static IDictionary<string, T> Copy<T>(this IDictionary<string, T> dict)
         where T : ICloneable
    {
        if (typeof(T).IsValueType)
        {
            return new Dictionary<string, T>(dict);
        }
        else
        {
            var copy = new Dictionary<string, T>();
            foreach (var pair in dict)
            {
                copy[pair.Key] = pair.Value;
            }
            return copy;
        }
    }
Related