Jawaban:
Oke, .NET 2.0 menjawab:
Jika Anda tidak perlu mengkloning nilai-nilai, Anda dapat menggunakan konstruktor berlebihan ke Kamus yang mengambil IDictionary yang ada. (Anda juga dapat menentukan pembanding sebagai pembanding kamus yang ada.)
Jika Anda tidak perlu untuk mengkloning nilai-nilai, Anda dapat menggunakan sesuatu seperti ini:
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;
}
Itu bergantung pada TValue.Clone()
menjadi klon yang dalam juga, tentu saja.
Clone()
metode apakah itu dalam atau dangkal. Saya telah menambahkan catatan untuk efek itu.
ConcurrentDictionary
.
(Catatan: meskipun versi kloning berpotensi berguna, untuk menyalin dangkal konstruktor yang saya sebutkan di posting lain adalah pilihan yang lebih baik.)
Seberapa dalam Anda menginginkan salinannya, dan versi .NET apa yang Anda gunakan? Saya menduga bahwa panggilan LINQ ke ToDictionary, menentukan kunci dan elemen pemilih, akan menjadi cara termudah untuk pergi jika Anda menggunakan .NET 3.5.
Misalnya, jika Anda tidak keberatan nilainya menjadi klon dangkal:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => entry.Value);
Jika Anda sudah membatasi T untuk mengimplementasikan ICloneable:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => (T) entry.Value.Clone());
(Itu belum diuji, tetapi harus bekerja.)
Dictionary<string, int> dictionary = new Dictionary<string, int>();
Dictionary<string, int> copy = new Dictionary<string, int>(dictionary);
Untuk .NET 2.0 Anda bisa mengimplementasikan kelas yang mewarisi dari Dictionary
dan mengimplementasikan 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;
}
}
Anda kemudian dapat mengkloning kamus hanya dengan memanggil Clone
metode. Tentu saja implementasi ini mensyaratkan bahwa jenis nilai dari kamus mengimplementasikan ICloneable
, tetapi jika tidak, implementasi generik sama sekali tidak praktis.
Ini berfungsi baik untuk saya
// assuming this fills the List
List<Dictionary<string, string>> obj = this.getData();
List<Dictionary<string, string>> objCopy = new List<Dictionary<string, string>>(obj);
Seperti yang dijelaskan Tomer Wolberg dalam komentar, ini tidak berfungsi jika tipe nilai adalah kelas yang bisa berubah.
Anda selalu dapat menggunakan serialisasi. Anda bisa membuat cerita bersambung objek lalu deserialisasi. Itu akan memberi Anda salinan yang mendalam dari Kamus dan semua item di dalamnya. Sekarang Anda dapat membuat salinan dalam dari objek apa pun yang ditandai sebagai [Serializable] tanpa menulis kode khusus apa pun.
Berikut adalah dua metode yang akan menggunakan Serialisasi Binary. Jika Anda menggunakan metode ini, Anda cukup menelepon
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;
}
Cara terbaik bagi saya adalah ini:
Dictionary<int, int> copy= new Dictionary<int, int>(yourListOrDictionary);
Metode Serialisasi Binary berfungsi dengan baik tetapi dalam tes saya itu menunjukkan 10x lebih lambat daripada implementasi non-serialisasi klon. MengujinyaDictionary<string , List<double>>
ToBinary()
dalam Serialize()
metode ini disebut dengan this
bukan yourDictionary
. Kemudian dalam FromBinary()
byte [] disalin pertama kali secara manual ke MemStream tetapi hanya dapat diberikan ke konstruktornya.
Itulah yang membantu saya, ketika saya mencoba menyalin Kamus <string, string>
Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);
Semoga berhasil
Coba ini jika kunci / nilai 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;
}
Membalas posting lama namun saya merasa berguna untuk membungkusnya sebagai berikut:
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
nilai mungkin lagi [sub] koleksi.