克隆/深层复制.NET通用字典<string,T>的最佳方法是什么?
我有一个通用字典字典,我想本质上做一个克隆()的任何build议。
好的,.NET 2.0的答案是:
如果您不需要克隆这些值,则可以使用构造函数重载到带有现有IDictionary的Dictionary。 (您也可以将比较器指定为现有字典的比较器。)
如果你确实需要克隆这些值,你可以使用像这样的东西:
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; }
当然,依靠TValue.Clone()
也是一个适当的深度克隆。
(注意:虽然克隆版本可能是有用的,但对于简单的浅拷贝,我在另一篇文章中提到的构造函数是更好的select。)
你想要多深的副本,你使用的是什么版本的.NET? 如果您使用.NET 3.5,我怀疑对ToDictionary的LINQ调用,指定键和元素select器,将是最简单的方法。
例如,如果你不介意作为浅层克隆的价值:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, entry => entry.Value);
如果你已经限制T来实现ICloneable:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, entry => (T) entry.Value.Clone());
(那些未经testing,但应该工作。)
Dictionary<string, int> dictionary = new Dictionary<string, int>(); Dictionary<string, int> copy = new Dictionary<string, int>(dictionary);
对于.NET 2.0,您可以实现一个从Dictionary
inheritance的类,并实现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; } }
然后您可以简单地通过调用Clone
方法来克隆字典。 当然这个实现要求字典的值types实现ICloneable
,否则一般的实现根本不可行。
你总是可以使用序列化。 你可以序列化对象然后反序列化它。 这将给你一个深层的字典及其内的所有项目的副本。 现在,您可以创build任何标记为[可序列化]的对象的深层副本,而无需编写任何特殊代码。
这里有两个将使用二进制序列化的方法。 如果您使用这些方法,只需致电
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; }
二进制序列化方法工作正常,但在我的testing中,它显示比克隆的非序列化实现慢10倍。 在Dictionary<string , List<double>>
上testing它
对我来说最好的办法是这样的:
Dictionary<int, int> copy= new Dictionary<int, int>(yourListOrDictionary);
如果键/值是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; }