views:

285

answers:

3

I know that we should rather be using dictionaries as opposed to hashtables. I cannot find a way to clone the dictionary though. Even if casting it to ICollection which I do to get the SyncRoot, which I know is also frowned upon. I am busy changing that now. I am under the correct assumption that there is no way to implement any sort of cloning in a generic way which is why clone is not supported for dictionary?

A: 

This is a quick and dirty clone method I once wrote...the initial idea is from CodeProject, I think.

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

Useage:

Dim clonedDict As Dictionary(Of String, String) = Clone(Of Dictionary(Of String, String))(yourOriginalDict)
Bobby
+3  A: 

Use the Constructor that takes a Dictionary. See this example

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

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

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

        dict = null;

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

And just for fun.. You can use LINQ! Which is a bit more Generic approach.

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

Edit

This should work well with Reference Types, i tried the following:

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

And the modified code from above

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

Which outputs "Filip Ekberg".

Filip Ekberg
Just keep in mind that the first approach will create a shallow copy, i.e. the objects are not copied as well. For strings that is not really an issue but for other reference types it may be.
Brian Rasmussen
With the LINQ-expression it should at least copy the references. And when the GC find dict and it's null, but the references are not, they shoulndn't be removed, am i right? So it _should_ work on reference types aswell.
Filip Ekberg
A: 

This is a code project page on doing a deep clone of a dictionary. http://www.codeproject.com/KB/recipes/DeepCloneDictionary.aspx?display=Print

btlog