List passed by ref - help me explain this behavior

Take a look at the following program:

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

I assumed that myList would go through ref and the result would be

 3 4 

The list is really "accepted by ref", but only the sort function is valid. The following statement is myList = myList2; has no effect.

Thus, the conclusion:

 10 50 100 

Can you help me explain this behavior? If really myList not passed in-ref (as it can be seen from myList = myList2 does not work), how does myList.Sort() ?

I assumed that this statement does not enter into force, and the output will be:

 100 50 10 
+63
list pass-by-reference c #
Nov 30 '10 at 6:49
source share
7 answers

You pass the link to the list, but yours does not pass the list variable by reference - therefore, when you call ChangeList value of the variable (that is, the link - you think "pointer") is copied - and the parameter value changes inside ChangeList not visible to TestMethod .

to try:

 private void ChangeList(ref List<int> myList) {...} ... ChangeList(ref myList); 

Then the link to the local variable myRef (as indicated in TestMethod ); Now, if you reassign a parameter inside ChangeList , you also reassign the variable inside TestMethod .

+79
Nov 30 '10 at 6:52
source share

Initially, it can be represented graphically as follows:

Init states

Then sorting is applied myList.Sort(); Sort collection

Finally, when you did: myList' = myList2 , you lost one of the links, but not the original, and the collection remained sorted.

Lost reference

If you use by reference ( ref ), then myList' and myList will become the same (only one link).

Note. I use myList' to represent the parameter that you use in ChangeList (because you gave the same name as the original)

+136
Apr 22 '13 at 22:41
source share

Here is an easy way to figure it out.

  • Your list is an object created on the heap. The variable myList is a reference to this object.

  • In C #, you never skip objects, you pass their references by value.

  • When accessing the list object through the passed link in ChangeList (when sorting, for example), the original list changes.

  • The assignment in the ChangeList method ChangeList performed for the reference value, so no changes have been made to the original list (still on the heap, but not specified in the method variable anymore).

+15
Nov 30 '10 at 7:13
source share

this link will help you understand how to follow the link in C #. In principle, when an object of a reference type is passed by value to a method, only the methods available on that object can modify the contents of the object.

For example, the List.sort () method modifies the contents of a list, but if you assign any other object to the same variable, this assignment is local to this method. This is why myList remains unchanged.

If we pass an object of a reference type using the ref keyword, we can assign some other object to the same variable and which will change the whole object.

+6
Nov 30 '10 at 7:00
source share

C # only makes a shallow copy when it passes by value, unless the object in question is executing ICloneable (which apparently does not have a List class).

This means that it copies the List itself, but the references to the objects inside the list remain unchanged; that is, pointers continue to reference the same objects as the original List .

If you change the values ​​of your new List links, you will also change the original List (since it refers to the same objects). However, you then change the fact that myList refers completely to the new List , and now only the original List refers to these integers.

Read the "Transmission Reference Type Parameters" section of this MSDN article in the "Transmit Parameters" section for more information.

"How to Clone a Shared List in C #" from StackOverflow talks about how to make a deep copy of a list.

+4
Nov 30 '10 at 7:24
source share

So far, I agree with what everyone said above. I have a different approach to this code. Basically you assign a new list to the local variable myList, not the global one. if you change the signature of ChangeList (List myList) to private void ChangeList (), you will see the result 3, 4.

Here are my considerations ... Although the list is passed by reference, consider it as passing a pointer variable by value. When you call ChangeList (myList), you pass a pointer to (Global) myList. Now this is stored in the (local) myList variable. So now your (local) myList and (global) myList point to the same list. Now you do the sorting => it works because the (local) myList refers to the original (global) myList Then you create a new list and assign a pointer to your (local) myList. But as soon as the function exits the (local) variable myList, it will be destroyed. NTN

 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; } } 
+3
Dec 22 '10 at 22:36
source share

Use the ref keyword.

Have a look at the final link here to understand the transfer options.
To be specific, look at this to understand the behavior of the code.

EDIT: Sort works by the same link (which is passed by value), and therefore the values ​​are ordered. However, assigning a new instance to a parameter will not work, because the parameter is passed by value unless you put ref .

Typing ref allows you to change the pointer to a link to a new instance of List in your case. Without ref you can work with an existing parameter, but you cannot point to anything else.

+2
Nov 30 '10 at 6:53
source share



All Articles