Список передан 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 ответов:
передачи ссылка на список, а как не передача списка переменных по ссылке - поэтому, когда вы звоните
ChangeList
the значение переменной (т. е. ссылка - думаю, "указатель") копируется - и изменения в значение параметра внутри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
, вы можете работать с существующим параметром, но не можете заставить его указать на что-то еще.