Respuestas:
De acuerdo, el .NET 2.0 responde:
Si no necesita clonar los valores, puede usar la sobrecarga del constructor en Dictionary que toma un IDictionary existente. (También puede especificar el comparador como el comparador del diccionario existente).
Si usted no necesita clonar los valores, puede usar algo como esto:
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;
}
Eso se basa en TValue.Clone()
ser un clon adecuadamente profundo también, por supuesto.
Clone()
método si es profundo o poco profundo. He añadido una nota a tal efecto.
ConcurrentDictionary
.
(Nota: aunque la versión de clonación es potencialmente útil, para una copia superficial simple, el constructor que menciono en la otra publicación es una mejor opción).
¿Qué tan profunda desea que sea la copia y qué versión de .NET está usando? Sospecho que una llamada LINQ a ToDictionary, que especifica tanto la clave como el selector de elementos, será la forma más fácil de hacerlo si está utilizando .NET 3.5.
Por ejemplo, si no le importa que el valor sea un clon superficial:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => entry.Value);
Si ya ha restringido a T para implementar ICloneable:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => (T) entry.Value.Clone());
(Esos no han sido probados, pero deberían funcionar).
Dictionary<string, int> dictionary = new Dictionary<string, int>();
Dictionary<string, int> copy = new Dictionary<string, int>(dictionary);
Para .NET 2.0, podría implementar una clase que herede Dictionary
e implemente 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;
}
}
Luego puede clonar el diccionario simplemente llamando al Clone
método. Por supuesto, esta implementación requiere que se implemente el tipo de valor del diccionario ICloneable
, pero de lo contrario, una implementación genérica no es práctica en absoluto.
Esto funciona bien para mi
// assuming this fills the List
List<Dictionary<string, string>> obj = this.getData();
List<Dictionary<string, string>> objCopy = new List<Dictionary<string, string>>(obj);
Como Tomer Wolberg describe en los comentarios, esto no funciona si el tipo de valor es una clase mutable.
Siempre puedes usar la serialización. Puede serializar el objeto y luego deserializarlo. Eso le dará una copia profunda del Diccionario y todos los elementos que contiene. Ahora puede crear una copia profunda de cualquier objeto que esté marcado como [Serializable] sin escribir ningún código especial.
Aquí hay dos métodos que utilizarán la serialización binaria. Si usa estos métodos, simplemente llame
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;
}
La mejor manera para mí es esta:
Dictionary<int, int> copy= new Dictionary<int, int>(yourListOrDictionary);
El método de serialización binaria funciona bien, pero en mis pruebas demostró ser 10 veces más lento que una implementación de clon sin serialización. Probado enDictionary<string , List<double>>
ToBinary()
el Serialize()
método se llama con en this
lugar de yourDictionary
. Luego, en FromBinary()
el byte [] se copia primero manualmente en MemStream, pero solo se puede suministrar a su constructor.
Eso es lo que me ayudó, cuando estaba tratando de copiar en profundidad un Diccionario <string, string>
Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);
Buena suerte
Pruebe esto si la clave / valores son ICloneable:
public static Dictionary<K,V> CloneDictionary<K,V>(Dictionary<K,V> dict) where K : ICloneable where V : ICloneable
{
Dictionary<K, V> 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<K, V>(dict);
}
else // prepare to clone key or value or both
{
newDict = new Dictionary<K, V>();
foreach (KeyValuePair<K, V> 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;
}
Respondiendo en una publicación anterior, sin embargo, me pareció útil envolverlo de la siguiente manera:
using System;
using System.Collections.Generic;
public class DeepCopy
{
public static Dictionary<T1, T2> CloneKeys<T1, T2>(Dictionary<T1, T2> dict)
where T1 : ICloneable
{
if (dict == null)
return null;
Dictionary<T1, T2> ret = new Dictionary<T1, T2>();
foreach (var e in dict)
ret[(T1)e.Key.Clone()] = e.Value;
return ret;
}
public static Dictionary<T1, T2> CloneValues<T1, T2>(Dictionary<T1, T2> dict)
where T2 : ICloneable
{
if (dict == null)
return null;
Dictionary<T1, T2> ret = new Dictionary<T1, T2>();
foreach (var e in dict)
ret[e.Key] = (T2)(e.Value.Clone());
return ret;
}
public static Dictionary<T1, T2> Clone<T1, T2>(Dictionary<T1, T2> dict)
where T1 : ICloneable
where T2 : ICloneable
{
if (dict == null)
return null;
Dictionary<T1, T2> ret = new Dictionary<T1, T2>();
foreach (var e in dict)
ret[(T1)e.Key.Clone()] = (T2)(e.Value.Clone());
return ret;
}
}
entry.Value
valor podría ser otra [sub] colección.