سؤال

I tried to search for my answer and found them in regards to C and not C# so thought of posting it.

My question might be trivial here.

As per my understanding (in simple terms)

After Copying has completed

Shallow Copy -> main and copied object (reference or value type) should point to the same object in memory

DeepCopy -> main and copied object (reference or value type) should point to different objects in memory

Going ahead with this, I have a structure in C# and trying to make a shallow copy of the same. I tried using "MemberwiseClone" method but I guess it works only for reference types. For value types i think "MemberwiseClone" method will box it into an object and unbox it into a different memory address in the stack.

What i have tried is as below.

My question is how (if at all possible) can I create a shallow copy of a simple structure?

I hope my fundamentals are correct here and not talking rubbish. Please correct me if I am wrong in any of the statements I have made.

Regards,

Samar

struct MyStruct : ICloneable
{
    public int MyProperty { get; set; }

    public object Clone()
    {
        return this.MemberwiseClone();//boxing into object
    }
}


    private void btnChkStr_Click(object sender, EventArgs e)
    {
        MyStruct struct1 = new MyStruct();
        struct1.MyProperty = 1;

        //MyStruct struct2 = struct1; //This will create a deep copy
        MyStruct struct2 = (MyStruct)(struct1.Clone());//unboxing into structure hence allocating a different memory address
        struct2.MyProperty = 2;

        MessageBox.Show(struct1.MyProperty.ToString()); //still showing 1
    }
هل كانت مفيدة؟

المحلول

Your expectation of what a deep copy vs a shallow copy does is not correct. A shallow copy copies all value types, and just the references of reference types. A deep copy copies all value types and all reference types.

So your struct already performs a shallow copy when doing:

MyStruct struct2 = struct1;

This code example (console application) shows, that changing a value of the object in the second struct changes also the value of the object in the first struct, because the object has just been copied by reference:

class Program
{
    static void Main(string[] args)
    {
        Test t1 = new Test();
        t1.i = 1;
        t1.o = new Klasse();
        t1.o.i = 1;

        Test t2 = t1;
        t2.i = 2;
        t2.o.i = 2;

        Console.WriteLine(t1.i.ToString());
        Console.WriteLine(t1.o.i.ToString());
        Console.WriteLine(t2.i.ToString());
        Console.WriteLine(t2.o.i.ToString());
        Console.Read();
    }
}

struct Test
{
    public int i;
    public Klasse o;
}

class Klasse
{
    public int i = 0;
}

نصائح أخرى

Your definition of a shallow copy can be achieved by explicitly boxing a struct. However, because the struct is boxed it's not easy to access it's properties!

void Main()
{
    object o1 = new M { A = 1 };
    object o2 = o1;

    // o2.A = 100 (this can also be done using dynamic)
    var prop = typeof(M).GetProperty("A");
    prop.SetValue(o2, 100);

    // prints 100, since both point to the same instance
    Console.WriteLine(((M)o1).A);
}

public struct M {
    public int A { get; set; }
}

In general, though assigning a struct to a new variable (or calling MemberwiseClone()), will copy all fields of the struct.

It's also worth noting that your definitions of deep and shallow copy are different than what is normally used. In general:

Shallow copy: a new instance of the object is created, so all of its members are copied by reference (e. g. a.X and shallowCopyOfA.X would still reference the same object). Members that are value types (e. g. structs, & primitives) are copied by value.

Deep copy: a new instance of the object is created, and all members are also deeply copied.

Not sure what you require of your "copy". As mentioned elsewhere, structs are already copied by value when assigned or passed to a method. So maybe you need nothing extra?

Maybe this is simply what you want (not sure if it's useful for anything!):

struct MyStruct : ICloneable
{
    public int MyProperty { get; set; }

    public MyStruct Clone()
    {
        return this;
    }
    object ICloneable.Clone()
    {
        return Clone();
    }
}

A word of warning: Your MyStruct is a so-called mutable struct because the set accessor of the auto-property is public. Many people consider mutable structs "evil" because the combination of value type semantics and mutability can lead to surprising behavior.

EDIT: If you want copy-by-reference semantics, why do you use a struct in the first place, rather than a class? A struct is not a reference to a location of the object, like a class is. As others have given examples of, boxing the MyStruct into an object variable will make that object be a reference to a box containing the MyStruct value. The reference to the box can be copied by reference.

You can create a class that contains just one instance field of type MyStruct. Then this class will be a "wrapping" of your struct into a reference type, and you can copy instances of such a class by usual reference type semantics (copy the reference, the object itself is not copied).

It is impossible to make such a shallow copy of a struct.

Consider using classes instead.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top