Câu trả lời:
Được rồi, câu trả lời .NET 2.0:
Nếu bạn không cần sao chép các giá trị, bạn có thể sử dụng quá tải hàm tạo cho Từ điển để có IDadata hiện có. (Bạn cũng có thể chỉ định bộ so sánh là bộ so sánh của từ điển hiện có.)
Nếu bạn làm cần phải sao chép các giá trị, bạn có thể sử dụng một cái gì đó như thế này:
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;
}
Điều đó phụ thuộc vào TValue.Clone()
việc là một bản sao sâu phù hợp là tốt, tất nhiên.
Clone()
phương pháp cho dù nó sâu hay nông. Tôi đã thêm một lưu ý cho hiệu ứng đó.
ConcurrentDictionary
.
(Lưu ý: mặc dù phiên bản nhân bản có khả năng hữu ích, đối với một bản sao nông đơn giản, hàm tạo mà tôi đề cập trong bài đăng khác là một lựa chọn tốt hơn.)
Bạn muốn bản sao sâu đến mức nào và bạn đang sử dụng phiên bản .NET nào? Tôi nghi ngờ rằng một cuộc gọi LINQ tới ToDipedia, chỉ định cả bộ chọn khóa và phần tử, sẽ là cách dễ nhất để sử dụng nếu bạn đang sử dụng .NET 3.5.
Ví dụ: nếu bạn không nhớ giá trị là một bản sao nông:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => entry.Value);
Nếu bạn đã hạn chế T để triển khai IClonizable:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => (T) entry.Value.Clone());
(Những người chưa được kiểm tra, nhưng nên làm việc.)
Dictionary<string, int> dictionary = new Dictionary<string, int>();
Dictionary<string, int> copy = new Dictionary<string, int>(dictionary);
Đối với .NET 2.0, bạn có thể triển khai một lớp kế thừa Dictionary
và thực hiện 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;
}
}
Sau đó, bạn có thể sao chép từ điển chỉ bằng cách gọi Clone
phương thức. Tất nhiên việc thực hiện này đòi hỏi loại giá trị của từ điển thực hiện ICloneable
, nhưng nếu không thì việc triển khai chung không thực tế chút nào.
Cái này làm việc tốt cho tôi
// assuming this fills the List
List<Dictionary<string, string>> obj = this.getData();
List<Dictionary<string, string>> objCopy = new List<Dictionary<string, string>>(obj);
Như Tomer Wolberg mô tả trong các bình luận, điều này không hoạt động nếu loại giá trị là một lớp có thể thay đổi.
Bạn luôn có thể sử dụng serialization. Bạn có thể tuần tự hóa đối tượng sau đó giải tuần tự hóa nó. Điều đó sẽ cung cấp cho bạn một bản sao sâu của Từ điển và tất cả các mục bên trong nó. Bây giờ bạn có thể tạo một bản sao sâu của bất kỳ đối tượng nào được đánh dấu là [Nối tiếp] mà không cần viết bất kỳ mã đặc biệt nào.
Đây là hai phương pháp sẽ sử dụng Binary serialization. Nếu bạn sử dụng các phương pháp này, bạn chỉ cần gọi
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;
}
Cách tốt nhất cho tôi là thế này:
Dictionary<int, int> copy= new Dictionary<int, int>(yourListOrDictionary);
Phương pháp tuần tự hóa nhị phân hoạt động tốt nhưng trong các thử nghiệm của tôi, nó cho thấy chậm hơn gấp 10 lần so với thực hiện không tuần tự hóa bản sao. Đã thử nó trênDictionary<string , List<double>>
ToBinary()
các Serialize()
phương pháp được gọi với this
thay vì yourDictionary
. Sau đó, trong FromBinary()
byte [] đầu tiên được sao chép thủ công vào MemStream nhưng nó chỉ có thể được cung cấp cho hàm tạo của nó.
Đó là điều đã giúp tôi, khi tôi đang cố gắng sao chép sâu một từ điển <chuỗi, chuỗi>
Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);
Chúc may mắn
Hãy thử điều này nếu khóa / giá trị có thể IClonizable:
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;
}
Trả lời trên bài viết cũ tuy nhiên tôi thấy nó hữu ích để bọc nó như sau:
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
giá trị có thể được nêu ra một [sub] bộ sưu tập.