2010-02-17 18 views
37

So che dovremmo piuttosto usare dizionari piuttosto che hashtables. Non riesco però a trovare un modo per clonare il dizionario. Anche se lo lanco su ICollection che faccio per ottenere SyncRoot, che conosco è anche disapprovato.Come si clona un dizionario in .NET?

Sono occupato a cambiarlo ora. Sono sotto il presupposto corretto che non c'è modo di implementare qualsiasi tipo di clonazione in un modo generico, motivo per cui clone non è supportato per il dizionario?

+3

Guardare http://stackoverflow.com/questions/139592/che-è-il-best-way-to-clone-deep-copy-a-net-generic-dictionarystring-t – sashaeve

+0

Ho visto che ma io non importa della copia profonda. Farà una copia poco profonda clone. Inoltre c'è una seconda parte alla mia domanda che è: è la ragione per cui non esiste un clone a causa della difficoltà che introduce il generico? – uriDium

risposta

56

utilizzare il costruttore che prende un dizionario. Vedi questo esempio

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

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

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

dict = null; 

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

E solo per divertimento .. È possibile utilizzare LINQ! Qual è un approccio un po 'più generico.

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

Modifica

Questo dovrebbe funzionare bene con i tipi di riferimento, ho provato la seguente:

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

E il codice modificato di cui sopra

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

quali uscite " Filip Ekberg ".

+9

Ricorda che il primo approccio creerà una copia superficiale, vale a dire che gli oggetti non vengono copiati. Per le stringhe che non è davvero un problema, ma per altri tipi di riferimento potrebbe essere. –

+0

Con l'espressione LINQ dovrebbe almeno copiare i riferimenti. E quando il GC trova dict ed è nullo, ma i riferimenti non lo sono, non verranno rimossi, vero? Quindi dovrebbe funzionare anche sui tipi di riferimento. –

+3

Vale la pena notare: questo approccio non clonerà 'IEqualityComparer' della fonte' IDictionary', cioè se si ha un 'IDictionary' con' StringComparer.OrdinalIgnoreCase'. –

2

Questo è un metodo clone rapido e sporco che ho scritto una volta ... l'idea iniziale è di CodeProject, penso.

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) 
Problemi correlati