Qual é a melhor maneira de clonar / copiar profundamente um dictionary genérico .NET ?

Eu tenho um dictionary genérico dictionary que eu gostaria essencialmente de fazer um Clone () de .. qualquer sugestão.

    Ok, as respostas do .NET 2.0:

    Se você não precisar clonar os valores, poderá usar a sobrecarga de construtor para o Dictionary, o que leva um IDictionary existente. (Você pode especificar o comparador como o comparador do dictionary existente também.)

    Se você precisar clonar os valores, poderá usar algo assim:

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

    Isso depende de TValue.Clone() ser um clone adequadamente profundo também, é claro.

    (Nota: embora a versão de clonagem seja potencialmente útil, para uma cópia superficial simples, o construtor que menciono no outro post é uma opção melhor.)

    Quão profundo você quer que a cópia seja, e qual versão do .NET você está usando? Eu suspeito que uma chamada LINQ para ToDictionary, especificando o seletor de chave e elemento, será a maneira mais fácil de ir se você estiver usando o .NET 3.5.

    Por exemplo, se você não se importa de o valor ser um clone superficial:

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

    Se você já restringiu T para implementar o ICloneable:

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

    (Esses não foram testados, mas devem funcionar.)

     Dictionary dictionary = new Dictionary(); Dictionary copy = new Dictionary(dictionary); 

    Para o .NET 2.0, você pode implementar uma class que herda do Dictionary e implementa ICloneable .

     public class CloneableDictionary : Dictionary where TValue : ICloneable { public IDictionary Clone() { CloneableDictionary clone = new CloneableDictionary(); foreach (KeyValuePair pair in this) { clone.Add(pair.Key, (TValue)pair.Value.Clone()); } return clone; } } 

    Você pode então clonar o dictionary simplesmente chamando o método Clone . É claro que essa implementação requer que o tipo de valor do dictionary implemente ICloneable , mas, de outra forma, uma implementação genérica não é nada prática.

    Você sempre pode usar serialização. Você poderia serializar o object e desserializá-lo. Isso lhe dará uma cópia detalhada do Dicionário e todos os itens dentro dele. Agora você pode criar uma cópia detalhada de qualquer object marcado como [Serializable] sem escrever nenhum código especial.

    Aqui estão dois methods que usarão serialização binária. Se você usar esses methods, basta ligar

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

    O método de serialização binária funciona bem, mas em meus testes ele mostrou ser 10x mais lento que uma implementação de não-serialização de clone. Testado no Dictionary>

    A melhor maneira para mim é esta:

     Dictionary copy= new Dictionary(yourListOrDictionary); 

    Este trabalho é bom para mim

      // assuming this fills the List List> obj = this.getData(); List> objCopy = new List>(obj); 

    Tente isto se chave / valores forem ICloneable:

      public static Dictionary CloneDictionary(Dictionary dict) where K : ICloneable where V : ICloneable { Dictionary newDict = null; if (dict != null) { // If the key and value are value types, just use copy constructor. if (((typeof(K).IsValueType || typeof(K) == typeof(string)) && (typeof(V).IsValueType) || typeof(V) == typeof(string))) { newDict = new Dictionary(dict); } else // prepare to clone key or value or both { newDict = new Dictionary(); foreach (KeyValuePair kvp in dict) { K key; if (typeof(K).IsValueType || typeof(K) == typeof(string)) { key = kvp.Key; } else { key = (K)kvp.Key.Clone(); } V value; if (typeof(V).IsValueType || typeof(V) == typeof(string)) { value = kvp.Value; } else { value = (V)kvp.Value.Clone(); } newDict[key] = value; } } } return newDict; } 

    Respondendo no post antigo, no entanto, achei útil envolvê-lo da seguinte maneira:

     using System; using System.Collections.Generic; public class DeepCopy { public static Dictionary CloneKeys(Dictionary dict) where T1 : ICloneable { if (dict == null) return null; Dictionary ret = new Dictionary(); foreach (var e in dict) ret[(T1)e.Key.Clone()] = e.Value; return ret; } public static Dictionary CloneValues(Dictionary dict) where T2 : ICloneable { if (dict == null) return null; Dictionary ret = new Dictionary(); foreach (var e in dict) ret[e.Key] = (T2)(e.Value.Clone()); return ret; } public static Dictionary Clone(Dictionary dict) where T1 : ICloneable where T2 : ICloneable { if (dict == null) return null; Dictionary ret = new Dictionary(); foreach (var e in dict) ret[(T1)e.Key.Clone()] = (T2)(e.Value.Clone()); return ret; } }