C# Copy/Clone Dictionary

How do I easily copy/clone the dictionary in employeeAudit[0] to employeeAudit[1]?

        static void Main(string[] args)
        {
            XElement doc = XElement.Load(AppConfig.GetPositionFile());

            List<EmployeeAudit> employeeAudit = new List<EmployeeAudit>();
            
            XElement e = doc.Element("entry");
            employeeAudit.Add(new EmployeeAudit());
            employeeAudit[0].Field("Timestamp",e.Attribute("timestamp").Value);
            employeeAudit[0].Field("Effective",e.Attribute("effective").Value);

            employeeAudit.Add(new EmployeeAudit());
            employeeAudit[1] = employeeAudit[0]; 
            employeeAudit[1].Field("Timestamp", "19551005");

        }       

    class EmployeeAudit
    {
        private Dictionary<string, string> Fields = new Dictionary<string,string>();

        public void Field(string fieldName, string fieldValue)
        {
            Fields[fieldName] = fieldValue;
        }
    }

Open in new window

nightshadzAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kyle AbrahamsSenior .Net DeveloperCommented:
Dictionary<string, string> x = new Dictionary<string,string>();
Dictionary<string, string> y = x.ToDictionary(i => i.Key, i => i.Value);

Open in new window

nightshadzAuthor Commented:
Apologies, I wasn't clear in my original question and thought he source code would be enough...

employeeAudit is a List of Type EmployeeAudit

I want to create a copy of the EmployeeAudit class, not a reference, for

employeeAudit[1] = employeeAudit[0];
Miguel OzSoftware EngineerCommented:
Please add a Clone method to your class:
    class EmployeeAudit
    {
        private Dictionary<string, string> Fields = new Dictionary<string,string>();

        public void Field(string fieldName, string fieldValue)
        {
            Fields[fieldName] = fieldValue;
        }

         public EmployeeAudit Clone ()
        {
            EmployeeAudit cloned = new EmployeeAudit();
            cloned.Fields = new Dictionary<string, string>(this.Fields);
            return cloned;
        }
   }

Open in new window

Usage:
employeeAudit[1] = employeeAudit[0].Clone(); 

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

käµfm³d 👽Commented:
Personally, just to add to Miguel's comment, I'd suggest calling the method "DeepClone" or "DeepCopy", so that it clearly expresses that the resulting object is just that.
nightshadzAuthor Commented:
Awesome! Thank you!!

kaufmed & miguel - Just to further my education, this doesn't really implement ICloneable, correct? It's kind of just filling a new dictionary and returning it as type EmployeeAudit.

I've looked at some examples that implement ICloneable but it's still a new concept to me. Would implementing ICloneable  do the same thing since I have to implement the Clone method regardless?  

What's cleaner or a 'best practice'? Writing my own clone method or using ICloneable?
käµfm³d 👽Commented:
The ICloneable interface is a highly debated topic. You'll see arguments on both sides that say its Clone method represents a shallow or deep copy. In the end, there's nothing forcing you to attach the ICloneable interface to your class simply because it has a Clone method. Attaching the interface would provide you with a level of abstraction, though, that could help you in other bits of your code. You would need to gauge if there's enough benefit for you to do so. If you do decide to implement the interface, then at the very least be consistent in how you implement it--if one class does a deep copy, then so should all the other classes which implement that interface, and vice versa. If this is a library that will be consumed by other applications (i.e. other developers), then you should clearly document what your Clone methods do.

Personally, I've always thought a "clone" as a deep copy. When Dolly was cloned, you didn't see two conjoined sheep running around--she was a distinct being herself.
nightshadzAuthor Commented:
Interesting. Doing a little more digging a came across this wiki article http://en.wikipedia.org/wiki/Object_copy and have a better understanding of what is going on now, I hope. To clarify, the code above that Miguel provided would be considered a deep copy since the old and new are referencing different objects in memory - this would be considered a deep copy since modifying any attribute of a would never affect b?
käµfm³d 👽Commented:
Correct, though you need to be careful when working with collections and reference and value types. For example, if I had classes defined as:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public  System.Collections.Gereric.List<Address> Addresses { get; set; }
}

class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

Open in new window


and I added a Clone method defined as:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public  System.Collections.Gereric.List<Address> Addresses { get; set; }

    public Person Clone()
    {
        Person clone= new Person();

        clone.FirstName = this.FirstName;
        clone.LastName = this.LastName;
        clone.Addresses = new List<Address>(this.Addresses);

        return clone;
    }
}

Open in new window


...then this would not be a deep copy because even though you are creating a new list of Address objects, the actual objects that are contained within this new list are the same exact objects that are in the existing list. Because anything that is a class is a reference type, assigning an instance to a variable only copies the reference, not the data itself. You would need a Clone method on the Address class as well:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public  System.Collections.Gereric.List<Address> Addresses { get; set; }

    public Person Clone()
    {
        Person clone= new Person();

        clone.FirstName = this.FirstName;
        clone.LastName = this.LastName;
        clone.Addresses = new List<Address>(this.Addresses.Count);

        foreach (Address adr in this.Addresses)
        {
            Address clonedAddress = adr.Clone();

            clone.Addresses.Add(clonedAddress);
        }

        return clone;
    }
}

class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }

    public Address Clone()
    {
        Address clone= new Address();

        clone.Street = this.Street;
        clone.City = this.City;
        clone.State = this.State;
        clone.Zip = this.Zip;

        return clone;
    }
}

Open in new window

nightshadzAuthor Commented:
Thank you so much for all the information!

While mucking around, I attempted to implement the code Kyle first posted and got it working. I merged it into the Clone method as follows:

        //Deep copy the Fields dictionary
        public Audit Clone()
        {
            Audit cloned = new Audit();
            //cloned.Fields = new Dictionary<string, string>(this.Fields);

            cloned.Fields = this.Fields.ToDictionary(i => i.Key, i => i.Value);
            return cloned;
        }

Open in new window


While it achieves the same result, it doesn't seem like it's the most efficient since it loops over every item in the dictionary. Correct me if I'm wrong please?
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.