2010-02-17 18 views
37

Sé que deberíamos usar diccionarios en lugar de hashtables. Sin embargo, no puedo encontrar la forma de clonar el diccionario. Incluso si lo lanzo a ICollection, lo cual hago para obtener SyncRoot, que sé que también está mal visto.¿Cómo se clona un diccionario en .NET?

Estoy ocupado cambiando eso ahora. ¿Estoy bajo la suposición correcta de que no hay forma de implementar ningún tipo de clonación de una manera genérica, y por eso el clon no es compatible con el diccionario?

+3

Mire en http://stackoverflow.com/questions/139592/what-is-the-best-way-to-clone-deep-copy-a-net-generic-dictionarystring-t – sashaeve

+0

Vi eso pero yo no me importa la copia profunda Una copia superficial clonará. También hay una segunda parte de mi pregunta que es: ¿Es la razón por la que no hay clon debido a la dificultad que presentan los genéricos? – uriDium

Respuesta

56

utilizar el constructor que toma un diccionario. Vea este ejemplo

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

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

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

dict = null; 

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

Y solo por diversión .. ¡Puede usar LINQ! Que es un enfoque un poco más genérico.

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

Editar

Esto debería funcionar bien con los tipos de referencia, He intentado lo siguiente:

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

Y el código modificado de arriba

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

que emite " Filip Ekberg ".

+9

Solo tenga en cuenta que el primer enfoque creará una copia poco profunda, es decir, los objetos no se copiarán también. Para cadenas que no es realmente un problema, pero para otros tipos de referencia puede ser. –

+0

Con la expresión LINQ, debería al menos copiar las referencias. Y cuando el GC encuentre dict y sea nulo, pero las referencias no lo son, no deberían eliminarse, ¿estoy en lo correcto? Por lo tanto, también debería funcionar en tipos de referencia. –

+3

Vale la pena señalar: este enfoque no clonará el 'IEqualityComparer' de la fuente' IDictionary', es decir, si tiene un 'IDictionary' con un' StringComparer.OrdinalIgnoreCase'. –

2

Este es un método de clonación rápido y sucio que una vez escribí ... la idea inicial es de CodeProject, creo.

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 

Uso:

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