tags:

views:

228

answers:

9

I have

class A
{
    public int a;
    public string b;
}

How can i copy A to another A? In C++ i know i could do *a1 = *a2;. Is there something similar in C#? I know i could write a generic solution using reflection but i hope something exist already.

I'm considering changing A to a nullable struct.

Step 2 i'll need to do

class B : A {}
class C : A {}

and copy the base data from B to C.

+3  A: 

Assuming A is just a simple class, you can do

A newA = instanceOfA.MemberwiseClone();

MemberwiseClone() is a shallow copy though, so if your class gets complex, with properties that are also reference types, this will not work for you.

womp
Although this cannot be as fast as a non-reflection approach.
Hamish Grubijan
Agreed. It can be more convenient and scalable than a custom approach however.
womp
+2  A: 

there is the ICloneable interface which offers up a Clone() method.

Clone on msdn.

runrunraygun
A: 

You can Clone, you can define a copy constructor. Why change class to struct just because in C++ you can do something in 10 characters. C# is different. Structs have advantages and disadvantages.

Hamish Grubijan
+1  A: 

Add the appropriate constructors:

class Foo
{
    public Foo(int a, string b)
    {
        A = a;
        B = b;
    }

    public Foo(Foo other)
    {
        A = other.A;
        B = other.B;
    }

    public int A { get; set; }
    public string B { get; set; }
}

You should also consider making it immutable, especially if you are considering making it into a struct. Mutable structs are evil.

Finally when you are inheriting from a class you don't need to copy the members from the base class into the subclass.

Mark Byers
+1 if I had enough votes today. Immutable would imply no set properties, right?
Hamish Grubijan
@lpthnc: `private set` would do it.
Bruno Reis
Thanks. How would you declare that if you want to keep get as public - on the same line or separately?
Hamish Grubijan
@Ipthnc: public int A { get; private set; }
Mark Byers
+6  A: 

I have used binary serialization. Basically, serialize the instance to a memory stream. Then, deserialize it out of the memory stream. You will have an exact binary copy. It will be a deep copy, rather than a shallow copy.

class a = new ClassA();

class b = MySerializationMethod(a);

For a shallow copy you can use Object.MemberwiseClone

Jride
+1 for this method. We've used this many times and it works great.
womp
It looks like Object.MemberwiseClone only works with the two classes are the same and within the class method? How might i program MySerializationMethod? It seems i'll be using reflection.
acidzombie24
someone posted it below: http://www.c-sharpcorner.com/UploadFile/sd_surajit/cloning05032007012620AM/cloning.aspxno reflection needed
Jride
+2  A: 

Here's what somebody has already done...

Deep Copy in C# (Cloning for a user defined class)

Partha Choudhury
A: 

wouldn't it be simpler to write the class to a stream and read it out into another class?

A: 

Here is some simple code that works on any class, not just base.

    public static void DuckCopyShallow(this Object dst, object src)
    {
        var srcT = src.GetType();
        var dstT= dst.GetType();
        foreach(var f in srcT.GetFields())
        {
            var dstF = dstT.GetField(f.Name);
            if (dstF == null)
                continue;
            dstF.SetValue(dst, f.GetValue(src));
        }

        foreach (var f in srcT.GetProperties())
        {
            var dstF = dstT.GetProperty(f.Name);
            if (dstF == null)
                continue;

            dstF.SetValue(dst, f.GetValue(src, null), null);
        }
    }
acidzombie24
A: 

We've used this code successfully:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Utility {
    internal static class ObjectCloner {
        public static T Clone<T>(T obj) {
            using (MemoryStream buffer = new MemoryStream()) {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(buffer, obj);
                buffer.Position = 0;
                T temp = (T)formatter.Deserialize(buffer);
                return temp;
            }
        }
    }
}

There may be other methods which work better, but perhaps this will help you

Chris

Chris Dunaway