2013-11-23 5 views
2

Клон является способом мелкой копии. string - ссылочный тип. почему изменение s2 не может повлиять на s1?метод Array.Clone - это мелкая копия?

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 + ","; 
     } 
    } 
} 

выходов: а, б, а, е, когда неполная копия, он должен быть: а, е, а, е

+0

но s2 = s1 это worked.when изменить s2, s1 изменить слишком – SleeplessKnight

+0

это важно понимать, что назначение s2 в s1 не неполную копию, а сделать точку s2 в s1, s2 эффективно делает указатель. Неглубокая копия означала бы создание нового массива и копирование указателей на каждый объект на новый массив. – Qwerty01

+0

Кто-нибудь знает, как поставить вопрос в качестве вопроса для голосования, я смущен ответами – SleeplessKnight

ответ

4

Когда вы клонs1 к s2, это два совершенно отдельных объекта, живущих в разных местах.

s1[1] содержит ссылку на место хранения b, равно как и s2[1]. Затем вы назначаете другую ссылку на s2[1] - одну в другое место. Это никак не влияет на s1[1].

В конце концов, вы не изменили то, что держит b.


При назначении s2 = s1; обе переменные указывают на тот же объект - при изменении этого объекта, то обе переменные будут отражать изменения, так как они указывают на то же место.

+0

Он просит неглубокую копию (например, в обоих массивах содержится те же объекты), проверьте мой пост, почему он не работает. – Qwerty01

2

Независимо от мелкой копии или глубокой копии, копирование всегда создает новый экземпляр. Это означает, что изменение скопированного объекта не повлияет на исходный объект. Обратите внимание, что когда я говорю , измените скопированный объект, я имею в виду, что вы назначаете некоторый элемент совершенно новому экземпляру. Если вы просто измените какое-либо свойство этого элемента, оно может отобразить соответствующий элемент в исходном массиве (конечно, если тип элемента ссылочный тип). Но в этом случае элемент является просто строкой, он неизменен и мы ничего не можем изменить на нем.

О мелкой копии и глубокой копии, вот немного от MSDN:

Мелкая копия массива копий только элементы массива, являются ли они ссылочные типы или типы значений, но это не копировать объекты, на которые ссылаются ссылки. Ссылки в новом массиве указывают на те же объекты, на которые указывают ссылки в исходном массиве.

Напротив, глубокая копия массива копирует элементы и все, что прямо или косвенно ссылается на элементы.

Я хотел бы подчеркнуть, больше на этом Изменение свойств элементов не означает изменения массива. И изменение массива означает, что вам нужно назначить некоторый элемент совершенно новому экземпляру.

+0

Это неправда. Мелкая копия для ссылочного типа влияет друг на друга. –

+0

@RohitVats, когда мы получаем доступ к некоторому элементу и ** изменяем какое-либо свойство этого элемента ** -> да, он изменит оригинал, но в этом случае. Можете ли вы сказать мне ** Какое свойство мы можем изменить на строке? ** –

+0

Вы не упомянули о строках в своем ответе. 'Независимо от мелкой копии или глубокой копии, копирование всегда создает новый экземпляр.' -> Это утверждение неверно в целом, это то, что я пытался сказать. –

2

То, что вы спрашиваете, невозможно, потому что строки неизменяемы, то есть они не могут быть назначены (больше информации на Why .NET String is immutable?), поэтому каждый раз, когда назначается строка, она фактически создает новую строку и заменяет объект.

Если вы хотите иметь эффект, который вы намеревались, вам нужно назначить s2 на s1, что бы заставить их указывать на один и тот же массив и иметь желаемый эффект.


Пример мелкой копии будет: (при условии, label1 и label2 определены)

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"; 

В конце концов привести Текст свойства s1 [1] будет изменено на «ASDF «потому что s1 [1] и s2 [1] указывают на один и тот же объект, даже если массивы разные.

Примечание: s2 [1] = new Label() не изменит s1 [1], потому что объект s2 [1] указывает на изменение (по существу, что s2 [1] = "asdf"; OP), но это ограничение любой мелкой копии.

+0

не могли бы вы дать мне правильный путь мелкой копии с 2 строковыми массивами – SleeplessKnight

+0

или дать мне демонстрацию мелкой копии без строки типа. спасибо – SleeplessKnight

+0

Я не вижу, как факт, что 'string' является неизменным, меняет что-либо. Назначение - это назначение, которое работает точно так же для любого ссылочного типа. – svick

0

Запустите программу ниже. Наверное, я прав. CopyTo, а также Clone выполняет теневую копию.

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(); 
     } 
    } 
} 
Смежные вопросы