Это вызов по ссылке?

У меня есть список массивов:

ArrayList ReceivedPackets = new ArrayList();

И у меня есть еще один ArrayList:

ArrayList returnList = ReceivedPackets;

Почему returnList теряет свое значение, когда я запускаю этот код?

ArrayList ReceivedPackets = new ArrayList();  // ReceivedPackets is empty
ReceivedPackets.Add(1);                       // Now it has an Integer
ArrayList returnList = ReceivedPackets;       // Call-by-Reference (I thought), returnList now has an Integer
ReceivedPackets.clear();                      // returnList is empty now. Why?

person Christoph    schedule 10.05.2016    source источник
comment
ArrayList является ссылочным типом   -  person Ehsan Sajjad    schedule 10.05.2016
comment
ReceivedPackets и returnList — две ссылочные переменные, которые указывают на один и тот же объект в памяти. Изменения этого объекта будут отражены в обоих.   -  person David    schedule 10.05.2016
comment
Как я могу обойтись без потери значения returnList?   -  person Christoph    schedule 10.05.2016
comment
ArraList.Copy() метод, который вы должны использовать, или ArrayList returnList = new ArrayList(ReceivedPackets);   -  person Ehsan Sajjad    schedule 10.05.2016
comment
Примечание: вызов по ссылке обычно подразумевает вызов метода... В вашем сообщении его нет.   -  person Alexei Levenkov    schedule 10.05.2016


Ответы (2)


Когда вы делаете это:

ArrayList returnList = ReceivedPackets;

Вы создаете новую переменную с именем returnList, но эта переменная указывает на тот же объект в памяти, что и ReceivedPackets. По-прежнему существует только один фактический ArrayList, просто на него указывают две переменные. Таким образом, изменения, внесенные в один, отражаются в обоих.

Как я могу обойтись без потери значения returnList?

Создайте новый объект. В простейшем случае это будет выглядеть так:

ArrayList returnList = new ArrayList();

Если вы также хотите, чтобы этот объект содержал все значения из ReceivedPackets, к счастью, ArrayList имеет перегрузку конструктора, которая делает именно это:

ArrayList returnList = new ArrayList(ReceivedPackets);

Теперь у вас будет два объекта, которые должны содержать копии одних и тех же данных. Изменения в одном не будут отражаться в другом.


В отсутствие этого конструктора ArrayList также имеет несколько CopyTo() методов, которые можно использовать для копирования элементов из одного в другой. В противном случае вы также можете вручную перебрать исходный ArrayList и скопировать элементы в место назначения ArrayList.

Возможно это может привести к путанице, если сам ArrayList содержит ссылочные объекты. Потому что они тоже могут иметь несколько «указателей» на один и тот же объект в памяти.

Например, если вы создаете один объект Widget и добавляете его к двум объектам ArrayList, то любые изменения, внесенные в объекты ArrayList (добавление/удаление элементов), будут независимыми, но любые изменения, внесенные в объект Widget, будут отражены в обоих объектах ArrayList. .

Дело в том, что ArrayList сам является объектом, независимым от содержащихся в нем объектов.

Таким образом, в зависимости от полного контекста того, что вы делаете, ваш пробег может варьироваться.

person David    schedule 10.05.2016

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

Если вы хотите создать глубокую копию, создайте новый объект.

static void Main() {
    ArrayList a = new ArrayList() {1,2,3};
    var b = a;
    var c = new ArrayList(a);

    a.Clear();
    Console.WriteLine(a.Count); // 0
    Console.WriteLine(b.Count); // 0
    Console.WriteLine(c.Count); // 3
}
person AntiTcb    schedule 10.05.2016