2

Clone is a way of shallow copy. string is a reference type. why s2's change can't affect s1?

    private void button3_Click(object sender, EventArgs e)
    {
        string[] s1 = { "a", "b" };
        string[] s2 = new string[2];

        s2 = (string[])s1.Clone();
         //s2=s1; //when Direct assignment s1 changed too
        s2[1] = "e";
        foreach (var s in s1)
        {
            this.richTextBox1.Text += s+",";
        }
        this.richTextBox1.Text += System.Environment.NewLine;

        foreach (var s in s2)
        {
            this.richTextBox1.Text += s + ",";
        }
    }
}

outputs: a,b, a,e, when shallow copy,it should be :a,e, a,e

SleeplessKnight
  • 2,125
  • 4
  • 20
  • 28
  • but s2=s1 it worked.when change s2, s1 change too – SleeplessKnight Nov 23 '13 at 17:47
  • it's important to realize that assigning s2 to s1 is not a shallow copy, but rather making s2 point to s1, effectively making s2 a pointer. A shallow copy would mean making a new array and copying the pointers to each object to the new array – Qwerty01 Nov 23 '13 at 17:53
  • anyone know how to make the question as a vote question , I am confused of answers – SleeplessKnight Nov 23 '13 at 18:37

4 Answers4

4

When you clone s1 to s2, these are two completely separate objects, living at different locations.

s1[1] holds a reference to the location that hold b, as does s2[1]. You then assign a different reference to s2[1] - one to a different location. This doesn't effect s1[1] in any way.

You have not changed what the location that holds b, after all.


When you assign s2 = s1;, both variables point to the same object - when you change that object, both variables will reflect the change, as they point to the same place.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • He's asking for a shallow copy (e.g. both arrays contain the same objects), check my post for why it doesn't work. – Qwerty01 Nov 23 '13 at 17:50
2

No matter shallow copy or deep copy, copying always creates a new instance. That means changing the copied object will not affect the original object. Note that when I say change the copied object, I mean you assign some element to a totally new instance. If you just change some property of that element, it can reflect the corresponding element in the original array (of course if the element type is reference type). But in this case the element is just a string, it's immutable and we can't change anything on it.

About shallow copy and deep copy, here is a little from MSDN:

A shallow copy of an Array copies only the elements of the Array, whether they are reference types or value types, but it does not copy the objects that the references refer to. The references in the new Array point to the same objects that the references in the original Array point to.

In contrast, a deep copy of an Array copies the elements and everything directly or indirectly referenced by the elements.

I would like to emphasize more on this Changing properties of elements does not mean changing the array. And changing an array means you have to assign some element to a totally new instance.

Community
  • 1
  • 1
King King
  • 61,710
  • 16
  • 105
  • 130
  • That's not true. Shallow copy for reference type do affect each other. – Rohit Vats Nov 23 '13 at 17:49
  • @RohitVats when we access to some element and **change some property of that element** -> yes it will change the original, but in this case Could you tell me **What property we can change on a string?** – King King Nov 23 '13 at 17:53
  • You didn't mentioned about strings in your answer. `No matter shallow copy or deep copy, copying always creates a new instance.` -> This statement is not true in general is what i was trying to say. – Rohit Vats Nov 23 '13 at 17:56
  • @RohitVats do you mean the array `s1` and `s2` should point to the same object? – King King Nov 23 '13 at 17:57
  • @KingKing the definition of a shallow copy of an array is a new array containing the exact same elements, while s1 and s2 are different objects, each of the elements in their arrays point to the same object (s1[0] == s2[0], s1[1] == s2[1], etc, but s1 != s2) – Qwerty01 Dec 04 '13 at 23:40
2

What you're asking is not possible because strings are immutable, meaning they cannot be assigned to (more info at Why .NET String is immutable?), therefore every time a string is assigned to, it's actually creating a new string and replacing the object.

If you wanted to have the effect you've intended, you would want to assign s2 to s1, which would make them point to the same array, and have the desired effect.


An example of a shallow copy would be: (assuming label1 and label2 are defined)

Label[] s1 = new Label[2];
Label[] s2 = new Label[2];
s1[0] = label1;
s1[1] = label2;
for (int i = 0; i < s1.Length; i++)
    s2[i] = s1[i];
s2[1].Text = "asdf";

In the end result the Text property of s1[1] will be changed to "asdf" because s1[1] and s2[1] point to the same object even though the arrays are different.

Note: s2[1] = new Label() would not change s1[1] because the object s2[1] is pointing to is changing (essentially what s2[1] = "asdf"; is doing in OP's code), but that is a limitation of any shallow copy.

Community
  • 1
  • 1
Qwerty01
  • 769
  • 8
  • 25
  • could you give me a right way of shallow copy with 2 string arraies – SleeplessKnight Nov 23 '13 at 18:01
  • I don't see how does the fact that `string` is immutable change anything. Assignment is assignment, that works exactly the same for any reference type. – svick Nov 23 '13 at 18:09
0

Run the below program. I guess I am correct. CopyTo aswell as Clone are performing shadow copy.

namespace ConsoleApplication5
{
    public class Person
    {
       public static void Main( string[] args)
       {
            StringBuilder a = new StringBuilder("Vish");
            StringBuilder b = new StringBuilder("Krish");
            StringBuilder[] arr = new  StringBuilder[2] { a,b };
            StringBuilder[] copied = new  StringBuilder[2];


            arr.CopyTo(copied, 0);

            StringBuilder[] cloned = arr.Clone() as  StringBuilder[];

            Console.WriteLine();

            copied[1] = copied[1].Append("_AppendedCopy");
            cloned[1] = cloned[1].Append("_AppendedClone");

            for (int i = 0; i < arr.Length; i++)
                Console.WriteLine(arr[i]);
            Console.WriteLine();
            for (int i = 0; i < copied.Length; i++)
                Console.WriteLine(copied[i]);
            Console.WriteLine();

            for (int i = 0; i < cloned.Length; i++)
                Console.WriteLine(cloned[i]);
            Console.WriteLine();

            Console.ReadKey();
        }
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Vishwas Rao
  • 121
  • 1
  • 1
  • 11