2010-02-17 63 views
37

我知道我们应该使用字典而不是哈希表。我找不到克隆字典的方法。即使将它投射到我收到SyncRoot的ICollection上,我也知道它也被忽视了。如何在.NET中克隆字典?

我现在正忙于改变这种情况。我是否有正确的假设,没有办法以通用的方式实现任何类型的克隆,这就是为什么字典不支持克隆的原因?

+3

看看http://stackoverflow.com/questions/139592/what-is-the-best-way-to-clone-deep-copy-a-net-generic-dictionarystring-t – sashaeve 2010-02-17 09:53:19

+0

我看到了,但我不关心深层复制。克隆浅拷贝可以做到。另外我的问题还有第二部分是:由于泛型引入的困难,是否没有克隆的原因? – uriDium 2010-02-17 12:55:06

回答

56

使用,需要一个字典的构造函数。看到这个例子

var dict = new Dictionary<string, string>(); 

dict.Add("SO", "StackOverflow"); 

var secondDict = new Dictionary<string, string>(dict); 

dict = null; 

Console.WriteLine(secondDict["SO"]); 

只是为了好玩..你可以使用LINQ!这是一个更通用的方法。

var secondDict = (from x in dict 
        select x).ToDictionary(x => x.Key, x => x.Value); 

编辑

这应该引用类型的工作很好,我试过如下:

internal class User 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public User Parent { get; set; } 
} 

并从上面

var dict = new Dictionary<string, User>(); 

dict.Add("First", new User 
    { Id = 1, Name = "Filip Ekberg", Parent = null }); 

dict.Add("Second", new User 
    { Id = 2, Name = "Test test", Parent = dict["First"] }); 

var secondDict = (from x in dict 
        select x).ToDictionary(x => x.Key, x => x.Value); 

dict.Clear(); 

dict = null; 

Console.WriteLine(secondDict["First"].Name); 

,输出修改后的代码“菲利普Ekberg“。

+9

请记住,第一种方法将创建一个浅拷贝,即不复制对象。对于不是真正的问题,但对于其他引用类型的字符串,可能是。 – 2010-02-17 10:05:25

+0

使用LINQ表达式,它应该至少复制引用。当GC找到字典并且它是空的,但是引用不是,它们不会被删除,对吗?所以它也应该适用于参考类型。 – 2010-02-17 10:09:10

+3

值得注意的是:这种方法不会克隆源IDictionary的'IEqualityComparer',也就是说,如果你有一个带'StringComparer.OrdinalIgnoreCase'的'IDictionary'。 – 2013-08-01 10:00:42

2

这是一个我曾经写过的快速而肮脏的克隆方法......我认为最初的想法是来自CodeProject。

Imports System.Runtime.Serialization 
Imports System.Runtime.Serialization.Formatters.Binary 

Public Shared Function Clone(Of T)(ByVal inputObj As T) As T 
    'creating a Memorystream which works like a temporary storeage ' 
    Using memStrm As New MemoryStream() 
     'Binary Formatter for serializing the object into memory stream ' 
     Dim binFormatter As New BinaryFormatter(Nothing, New StreamingContext(StreamingContextStates.Clone)) 

     'talks for itself ' 
     binFormatter.Serialize(memStrm, inputObj) 

     'setting the memorystream to the start of it ' 
     memStrm.Seek(0, SeekOrigin.Begin) 

     'try to cast the serialized item into our Item ' 
     Try 
      return DirectCast(binFormatter.Deserialize(memStrm), T) 
     Catch ex As Exception 
      Trace.TraceError(ex.Message) 
      return Nothing 
     End Try 
    End Using 
End Function 

用途:

Dim clonedDict As Dictionary(Of String, String) = Clone(Of Dictionary(Of String, String))(yourOriginalDict)