当前位置:  开发笔记 > 编程语言 > 正文

克隆/深度复制.NET泛型字典<string,T>的最佳方法是什么?

如何解决《克隆/深度复制.NET泛型字典<string,T>的最佳方法是什么?》经验,为你挑选了6个好方法。

我有一个通用词典词典,我想基本上做一个克隆()的任何建议.



1> Jon Skeet..:

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

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

例如,如果您不介意该值是浅层克隆:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
                                               entry => entry.Value);

如果您已经限制T实现ICloneable:

var newDictionary = oldDictionary.ToDictionary(entry => entry.Key, 
                                               entry => (T) entry.Value.Clone());

(这些是未经测试的,但应该有效.)


@Pratik:他们是lambda表达式 - C#3的一部分.
默认情况下,LINQ的ToDictionary不复制比较器。您在其他答案中提到过复制比较器,但是我认为此版本的克隆也应该通过比较器。

2> Jon Skeet..:

好的,.NET 2.0回答:

如果您不需要克隆值,则可以使用构造函数重载到Dictionary,它接受现有的IDictionary.(您也可以将比较器指定为现有字典的比较器.)

如果确实需要克隆值,可以使用以下内容:

public static Dictionary CloneDictionaryCloningValues
   (Dictionary original) where TValue : ICloneable
{
    Dictionary ret = new Dictionary(original.Count,
                                                            original.Comparer);
    foreach (KeyValuePair entry in original)
    {
        ret.Add(entry.Key, (TValue) entry.Value.Clone());
    }
    return ret;
}

当然,这也依赖于TValue.Clone()适当的深度克隆.


@ChrisW:那就是要求克隆每个值 - 这取决于`Clone()`方法,无论是深度还是浅度.我已经添加了一个注释.

3> Herald Smit..:
Dictionary dictionary = new Dictionary();

Dictionary copy = new Dictionary(dictionary);


这绝对有效 - 它创建了键和值的克隆.当然,这仅在值不是引用类型时有效,如果值是引用类型,则它实际上仅将键的副本作为浅副本.
值的指针仍然相同,如果对复制中的值应用更改,更改也将反映在字典对象中.
@UğurAldanmaz你忘记测试对引用对象的实际更改,你只测试克隆字典中值指针的替换,这显然有效,但如果你只更改测试对象的属性,你的测试将失败,如下所示:https:/ /dotnetfiddle.net/xmPPKr
@FokkoDriesprong不,它只是复制新对象中的keyValuePairs

4> Compile This..:

对于.NET 2.0,您可以实现一个继承自Dictionary和实现的类ICloneable.

public class CloneableDictionary : Dictionary where TValue : ICloneable
{
    public IDictionary Clone()
    {
        CloneableDictionary clone = new CloneableDictionary();

        foreach (KeyValuePair pair in this)
        {
            clone.Add(pair.Key, (TValue)pair.Value.Clone());
        }

        return clone;
    }
}

然后,您只需调用该Clone方法即可克隆字典.当然,这种实现要求字典的值类型实现ICloneable,但是否则通用实现根本不实用.



5> Shaun Bowe..:

您始终可以使用序列化.您可以序列化对象,然后反序列化它.这将为您提供字典的深层副本及其中的所有项目.现在,您可以创建标记为[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;
}



6> 小智..:

对我来说最好的方法是:

Dictionary copy= new Dictionary(yourListOrDictionary);


这不是复制引用,而不是值吗,因为Dictionary是引用类型?这意味着如果您更改其中一个的值,将会更改另一个的值?
推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有