Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struct or Deep copy - C#

I have finally managed to copy a value type of my object, A class that uses a dictionary to store dynamic properties. I was wondering about two things though, mono compatibility and efficiency. I am new to C# and still have plenty to learn about programming in general, so apologies if I am misusing a few phrases :P

I used this method How do you do a deep copy of an object in .NET (C# specifically)? ... to copy my object. I will also have hundreds of these objects, and was wondering copying them in this fashion was very inefficient? Would structs be a better option? I am not sure when to use structs however. An could it be ported with mono? Some googling suggest this serialisation could give rise to a problem.

like image 284
marked Avatar asked Jun 09 '11 16:06

marked


People also ask

Can I copy a struct in C?

We can also use assignment operator to make copy of struct. A lot of people don't even realize that they can copy a struct this way because one can't do same it with an array. Similarly one can return struct from a function and assign it but not array. The compiler do all the copying stuff behind the scene for us.

What is a deep copy C?

A deep copy, in contrast, means that you copy an entire object (struct). If it has members that can be copied shallow or deep, you also make a deep copy of them.

How do you deep copy a struct?

To perform a deep copy you must first free any memory that was being pointed to by the destination structure. Then allocate enough memory to hold the strings pointed to by the source structure. Now, strncpy the strings over. Save this answer.


2 Answers

Based upon follow up responses in the comments, the best solution to what you're looking for is the simplest one: write the code to copy the object yourself.

If your class is really as simple as a wrapper around a dictionary that stores key/value pairs for custom properties, you can use the Dictionary(IDictionary) constructor to copy the values from one dictionary to another.

class MyWrapper
{
    private Dictionary<string, object> properties = 
                                         new Dictionary<string, object>();

    public MyWrapper Clone()
    {
        MyWrapper output = new MyWrapper();

        output.properties = new Dictionary<string, object>(properties);
    }
}

Obviously, this is a simplified class that doesn't actually do anything, but from what you've described this should get you what you need. No reflection, no "gotchas", just a simple copy of values from one dictionary to another.

EDIT

I can't speak to mono portability, as I'm a Windows-only developer, but as for efficiency, an explicit solution where you copy what you need will be a hands-down winner over a reflection-based solution.

The concept of a true deep copy of any arbitrary type is not something easily (or even safely) achieved in a reference-based object-oriented language. While simple classes would be trivial to copy, reference loops, classes without parameterless constructors, and immutable types present challenges.

For instance, consider this class:

public class Foo
{
    public Foo Next { get; set; }
}

Which is pretty much the simplest implementation of a singly-linked list. A naive deep copy algorithm would start at the first instance of Foo, then clone it by recursively navigating down the chain of Next references until it encountered a null value. However, doing this, we'll not only eat up memory but also end up with objects that do not represent an actual clone of the original:

Foo first = new Foo();

first.Next = new Foo();

first.Next.Next = first;

This is a perfectly legal (and even reasonable) thing to do, but now we have a circular reference loop that will blow up our naive cloning algorithm. So now we have to implement an object cache.

Dictionary<object, object> clonedObjects;

Now, in the clone algorithm, when assigning values to properties or fields, we check the cache to see if the reference we're about to duplicate has already been cloned. If it has, we use that value instead of cloning a new one. This will give us a brand new object graph that represents our original object and is also a complete clone. Great, right?

Now, what about parameterless constructors? This one isn't even solvable in a completely generic sense. If I create this class:

public class Bar
{
    public Bar(string gotcha) { }
}

There's no way to clone this class in a naive sense; since you have no way of knowing how to call the constructor (you can obtain the ConstructorInfo reflectively, but the semantics of how it's called will be completely unknown. The best you could do would be to store metadata (by way of a custom attribute on the class) about which constructor to call and how to call it (a list of fields in the order that they should be passed, for example), but that requires previous knowledge of the cloning mechanism and also implies that the arguments for the constructor are fields on the original object, which is not necessarily the case.

Now we throw another snag into the mix: immutable reference types. This one can also potentially result in unexpected behavior. Immutable reference types are reference types whose (externally visible) value cannot change; in most cases, these classes are designed to exhibit value-type semantics. They also frequently lack parameterless constructors (and may not even have a publicly-accessible constructors at all), making them suffer from our previous irritation, but they may also use a factory-based method so that they can ensure that referential equality also means value equality, and vice versa (this latter condition is less common, but if we're talking about an algorithm that is a totally naive cloning mechanism, then we have to cover it). This, again, means another custom attribute to indicate that the cloning mechanism should simply copy the reference rather than cloning the actual object.

So, in short, a completely naive deep copy mechanism simply isn't possible when dealing with arbitrary types. Types would have to be designed with the cloning mechanism in mind, and may have to make concessions or decorate themselves in a particular way in order to work with it. This, combined with the relatively infrequent requirement, is likely why there is no framework-level deep copy mechanism now, and why you should consider a more explicit copying mechanism where you know what to copy (and what may not matter) so that you can be certain that what you get is what you want.

like image 181
Adam Robinson Avatar answered Oct 05 '22 01:10

Adam Robinson


Structs have some unique characteristics that should be heavily considered before using them.

  • They all are values types (this will add challenges to passing them around)
  • They all take up memory on the stack instead of the heap
  • they must have parameterless constructors
  • no inheritance for structs

http://msdn.microsoft.com/en-us/library/aa288471(v=vs.71).aspx

Take those points into consideration before asking whether or not structs are a viable option for your situation.

I generally would stick with just writing a method for my class the creates a deep copy. You could probably get real fancy and use a combination of generics and reflection to write a pretty abstract DeepClone<T>(T object) sort of method. Or take the easy road and just write one tailor fitted to the class in question.

like image 43
Matthew Cox Avatar answered Oct 05 '22 02:10

Matthew Cox