Список передан ref-помогите мне объяснить это поведение
взгляните на следующую программу:
class Test
{
List<int> myList = new List<int>();
public void TestMethod()
{
myList.Add(100);
myList.Add(50);
myList.Add(10);
ChangeList(myList);
foreach (int i in myList)
{
Console.WriteLine(i);
}
}
private void ChangeList(List<int> myList)
{
myList.Sort();
List<int> myList2 = new List<int>();
myList2.Add(3);
myList2.Add(4);
myList = myList2;
}
}
я предположил, что myList прошел бы мимо ref и вывода
3
4
список действительно "передается по ссылке", но только
7 ответов:
передачи ссылка на список, а как не передача списка переменных по ссылке - поэтому, когда вы звоните
ChangeListthe значение переменной (т. е. ссылка - думаю, "указатель") копируется - и изменения в значение параметра внутриChangeListне виделиTestMethod.попробуй:
мимо ссылка на локальная переменнаяprivate void ChangeList(ref List<int> myList) {...} ... ChangeList(ref myList);myRef(как заявлено вTestMethod); Теперь, если вы переназначите параметр внутриChangeListвы также переназначение переменной внутриTestMethod.
первоначально он может быть представлен графически следующим образом:
затем применяется сортировка
myList.Sort();наконец, когда вы сделали:
myList' = myList2, вы потеряли один из ссылки, но не оригинал и коллекция осталась отсортированной.
если вы используете ссылки (
ref), тоmyList'иmyListстанет таким же (только одна ссылка).Примечание: я использую
myList'представлять параметр, который вы используете вChangeList(потому что вы дали то же имя, что и оригинал)
вот простой способ понять это
ваш список-это объект, созданный в куче. Переменная
myList- Это ссылка на этот объект.в C# вы никогда не передаете объекты, вы передаете их ссылки по значению.
при доступе к объекту списка через переданную ссылку в
ChangeList(например, при сортировке) исходный список изменяется.назначение на
ChangeListметод сделан к значению ссылки, следовательно никакие изменения не сделаны к первоначальному списку (все еще на куче но не ссылаются на переменную метода больше).
этой ссылка поможет вам в понимании пройти по ссылке в C#. В принципе, когда объект ссылочного типа передается по значению методу, только методы, доступные на этом объекте, могут изменять содержимое объекта.
список.метод sort () изменяет содержимое списка, но если вы назначаете какой-либо другой объект той же переменной, это назначение является локальным для этого метода. Поэтому мой список остается неизменным.Если мы передаем объект ссылочный тип с помощью ключевого слова ref, то мы можем назначить какой-то другой объект той же переменной и что изменяет весь объект сам по себе.
C# просто делает мелкую копию, когда она проходит по значению, если объект, о котором идет речь, не выполняет
ICloneable(который, видимо,Listкласса нет).это означает, что он копирует
Listсам, но ссылки на объекты внутри списка остаются теми же; то есть указатели продолжают ссылаться на те же объекты, что и исходныйList.если вы измените значения вещей ваш новый
Listссылки, изменить оригиналListтакже (поскольку он ссылается на те же объекты). Однако вы тогда измените то, чтоmyListссылки полностью, на новыйListи теперь только оригиналListссылается на эти числа.читать Передача Параметров Ссылочного Типа С эта статья MSDN о "передаче параметров" для получения дополнительной информации.
" как клонировать общий список в C#" из StackOverflow рассказывает о том, как чтобы сделать глубокую копию списка.
хотя я согласен с тем, что сказано выше. У меня другой взгляд на этот код. в основном вы назначаете новый список локальной переменной myList, а не глобальной. если вы измените подпись ChangeList (List myList) на private void ChangeList (), вы увидите результат 3, 4.
вот мои рассуждения... Даже если список передается по ссылке, думайте об этом как о передаче переменной указателя по значению Когда вы называете группу(мой список) ты мимо указатель на (глобальный) myList. Теперь это хранится в переменной (local)myList. Итак, теперь ваш (локальный)myList и (глобальный) myList указывают на один и тот же список. Теперь вы делаете сортировку => это работает, потому что (локальный)myList ссылается на исходный (глобальный)myList Затем вы создаете новый список и назначаете указатель на этот ваш (локальный)myList. Но как только функция выходит (локальная)переменная myList уничтожается. ХТ
class Test { List<int> myList = new List<int>(); public void TestMethod() { myList.Add(100); myList.Add(50); myList.Add(10); ChangeList(); foreach (int i in myList) { Console.WriteLine(i); } } private void ChangeList() { myList.Sort(); List<int> myList2 = new List<int>(); myList2.Add(3); myList2.Add(4); myList = myList2; } }
использовать
refключевое слово.посмотрите на окончательную ссылку здесь чтобы понять параметры передачи.
Чтобы быть конкретным, посмотрите на этой, чтобы понять поведение кода.EDIT:
Sortработает на той же ссылке (которая передается по значению) и, следовательно, значения упорядочены. Однако назначение нового экземпляра параметру не будет работать, потому что параметр передается по значению, если вы не поместитеref.положить
refпозволяет изменить указатель на ссылку на новый экземплярListв вашем случае. Безref, вы можете работать с существующим параметром, но не можете заставить его указать на что-то еще.


