C# 克隆/深度复制.NET通用词典的最佳方法是什么<;字符串,T>;?

C# 克隆/深度复制.NET通用词典的最佳方法是什么<;字符串,T>;?,c#,generics,collections,clone,C#,Generics,Collections,Clone,我有一本通用字典字典,我想从本质上对它进行克隆()。任何建议 (注意:虽然克隆版本可能有用,但对于简单的浅层复制,我在另一篇文章中提到的构造函数是一个更好的选择。) 您希望副本有多深,以及您使用的.NET版本是什么?如果您使用的是.NET3.5,我怀疑对ToDictionary的LINQ调用(同时指定键和元素选择器)将是最简单的方法 例如,如果您不介意值为浅克隆: var newDictionary = oldDictionary.ToDictionary(entry => entry.K

我有一本通用字典
字典
,我想从本质上对它进行克隆()。任何建议

(注意:虽然克隆版本可能有用,但对于简单的浅层复制,我在另一篇文章中提到的构造函数是一个更好的选择。)

您希望副本有多深,以及您使用的.NET版本是什么?如果您使用的是.NET3.5,我怀疑对ToDictionary的LINQ调用(同时指定键和元素选择器)将是最简单的方法

例如,如果您不介意值为浅克隆:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
                                               entry => entry.Value);
如果您已经限制T实现iClonable:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, 
                                               entry => (T) entry.Value.Clone());
    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;
    }

(这些未经测试,但应该可以使用。)

好的,.NET 2.0回答:

如果不需要克隆这些值,可以使用构造函数重载到字典,该字典接受现有的IDictionary。(也可以将比较器指定为现有词典的比较器。)

如果确实需要克隆这些值,可以使用以下方法:

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;
}
公共静态字典clonedictionary值
(字典原文)其中TValue:iClonable
{
Dictionary ret=新字典(original.Count,
原件(比较器);
foreach(原始的KeyValuePair条目)
{
ret.Add(entry.Key,(TValue)entry.Value.Clone());
}
返回ret;
}

当然,这取决于
TValue.Clone()
也是一个适当的深度克隆。

对于.NET 2.0,您可以实现一个类,该类继承自
字典,并实现
iClonable

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;
    }
}
公共类CloneableDictionary:Dictionary,其中TValue:ICloneable
{
公共IDictionary克隆()
{
CloneableDictionary克隆=新的CloneableDictionary();
foreach(此处为KeyValuePair对)
{
添加(pair.Key,(TValue)pair.Value.clone());
}
返回克隆;
}
}

然后,只需调用
clone
方法即可克隆字典。当然,此实现要求字典的值类型实现ICloneable,但否则通用实现根本不实用。

您可以始终使用序列化。您可以序列化对象,然后反序列化它。这将给你一本字典的深度副本和里面的所有项目。现在,您可以创建标记为[Serializable]的任何对象的深度副本,而无需编写任何特殊代码

这里有两种方法将使用二进制序列化。如果使用这些方法,只需调用

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;
}

二进制序列化方法工作得很好,但在我的测试中,它比克隆的非序列化实现慢10倍。在
Dictionary

Dictionary Dictionary=newdictionary()上测试;
字典副本=新字典(字典);

对我来说,最好的方法是:

Dictionary<int, int> copy= new Dictionary<int, int>(yourListOrDictionary);
Dictionary copy=新词典(yourListOrDictionary);

如果键/值可克隆,请尝试以下操作:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, 
                                               entry => (T) entry.Value.Clone());
    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;
    }
publicstaticdictionary-CloneDictionary(Dictionary-dict)其中K:ICloneable其中V:ICloneable
{
字典newDict=null;
if(dict!=null)
{
//如果键和值是值类型,只需使用复制构造函数。
if(((typeof(K).IsValueType | | typeof(K)==typeof(string))&&
(typeof(V).IsValueType)| | typeof(V)==typeof(string)))
{
newDict=新字典(dict);
}
else//准备克隆键或值或两者
{
newDict=新字典();
foreach(dict中的KeyValuePair kvp)
{
K键;
if(typeof(K).IsValueType | | typeof(K)==typeof(string))
{
key=kvp.key;
}
其他的
{
key=(K)kvp.key.Clone();
}
V值;
if(typeof(V).IsValueType | | typeof(V)==typeof(string))
{
值=kvp.值;
}
其他的
{
value=(V)kvp.value.Clone();
}
newDict[key]=值;
}
}
}
返回newDict;
}

回复旧帖子,但我发现将其包装如下很有用:

使用系统;
使用System.Collections.Generic;
公共类深度复制
{
公共静态词典克隆键(Dictionary dict)
其中T1:ICloneable
{
if(dict==null)
返回null;
字典ret=新字典();
foreach(dict中的变量e)
ret[(T1)e.Key.Clone()]=e.Value;
返回ret;
}
公共静态词典克隆值(Dictionary dict)
其中T2:ICloneable
{
if(dict==null)
返回null;
字典ret=新字典();
foreach(dict中的变量e)
ret[e.Key]=(T2)(e.Value.Clone());
返回ret;
}
公共静态字典克隆(字典目录)
其中T1:ICloneable
其中T2:ICloneable
{
if(dict==null)
返回null;
字典ret=新字典();
foreach(dict中的变量e)
ret[(T1)e.Key.Clone()]=(T2)(e.Value.Clone());
返回ret;
}
}
这对我来说很好

 // assuming this fills the List
 List<Dictionary<string, string>> obj = this.getData(); 

 List<Dictionary<string, string>> objCopy = new List<Dictionary<string, string>>(obj);
//假设列表中已满
List obj=this.getData();
List objCopy=新列表(obj);

正如Tomer Wolberg在评论中所描述的那样,如果值类型是可变类,则这不起作用

当我试图深度复制一本字典时,

Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);
Dictionary dict2=新字典(dict);

祝你好运,如果你有“object”和object的字典