Yanıtlar:
Tamam, .NET 2.0 cevaplar:
Değerleri klonlamanıza gerek yoksa, varolan bir IDictionary alan Sözlük için aşırı yükleyici kullanabilirsiniz. (Karşılaştırıcıyı mevcut sözlüğün karşılaştırıcısı olarak da belirleyebilirsiniz.)
Eğer varsa do değerleri klonlamak gerekir, böyle bir şey kullanabilirsiniz:
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;
}
Tabii ki TValue.Clone()
bu da uygun bir şekilde derin bir klon olmaya dayanır .
Clone()
derin ya da sığ olmasının yöntemine bağlı. Bu etkiye bir not ekledim.
ConcurrentDictionary
.
(Not: klonlama sürümü potansiyel olarak yararlı olsa da, basit bir sığ kopya için diğer yazıda bahsettiğim yapıcı daha iyi bir seçenektir.)
Kopyanın ne kadar derin olmasını istiyorsunuz ve hangi .NET sürümünü kullanıyorsunuz? ToDictionary için LINQ çağrısı, hem anahtar hem de öğe seçici belirterek, .NET 3.5 kullanıyorsanız gitmek için en kolay yolu olacağını sanıyorum.
Örneğin, değerin sığ bir klon olduğunu düşünmezseniz:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => entry.Value);
T'yi ICloneable uygulamak için zaten kısıtladıysanız:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => (T) entry.Value.Clone());
(Bunlar test edilmemiştir, ancak çalışmalıdır.)
Dictionary<string, int> dictionary = new Dictionary<string, int>();
Dictionary<string, int> copy = new Dictionary<string, int>(dictionary);
.NET 2.0 için miras alan Dictionary
ve uygulayan bir sınıf uygulayabilirsiniz 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;
}
}
Daha sonra, sadece Clone
yöntemi çağırarak sözlüğü klonlayabilirsiniz . Elbette bu uygulama, sözlüğün değer türünün uygulanmasını gerektirir ICloneable
, ancak aksi halde genel bir uygulama hiç pratik değildir.
Bu benim için iyi çalışıyor
// assuming this fills the List
List<Dictionary<string, string>> obj = this.getData();
List<Dictionary<string, string>> objCopy = new List<Dictionary<string, string>>(obj);
Tomer Wolberg'in yorumlarda açıkladığı gibi, değer türü değiştirilebilir bir sınıfsa bu çalışmaz.
Serileştirmeyi her zaman kullanabilirsiniz. Nesneyi serileştirebilir ve ardından serisini kaldırabilirsiniz. Bu size Sözlüğün ve içindeki tüm öğelerin derin bir kopyasını verecektir. Artık [Serializable] olarak işaretlenmiş herhangi bir nesnenin özel bir kod yazmadan derin bir kopyasını oluşturabilirsiniz.
İşte İkili Serileştirmeyi kullanacak iki yöntem. Bu yöntemleri kullanırsanız,
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;
}
İkili Serileştirme yöntemi iyi çalışıyor ancak testlerimde klonun serileştirilmemiş bir uygulamasından 10 kat daha yavaş olduğu gösterildi. Üzerinde test edildiDictionary<string , List<double>>
ToBinary()
Serialize()
this
yourDictionary
FromBinary()
Bir Sözlük <string, string> derin kopyalamaya çalışırken bana yardımcı oldu
Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);
İyi şanslar
Anahtar / değerler ICloneable ise bunu deneyin:
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;
}
Eski yazı üzerine cevap ancak ben aşağıdaki gibi sarmak için yararlı buldum:
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
Değer bir başka [sub] Koleksiyonu olabilir.