List passed by ref - help me explain this behaviour

后端 未结 8 2269
名媛妹妹
名媛妹妹 2020-12-02 05:39

Take a look at the following program:

class Test
{
    List myList = new List();

    public void TestMethod()
    {
        myList.Add         


        
相关标签:
8条回答
  • 2020-12-02 06:06

    You are passing a reference to the list, but your aren't passing the list variable by reference - so when you call ChangeList the value of the variable (i.e. the reference - think "pointer") is copied - and changes to the value of the parameter inside ChangeList aren't seen by TestMethod.

    try:

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

    This then passes a reference to the local-variable myRef (as declared in TestMethod); now, if you reassign the parameter inside ChangeList you are also reassigning the variable inside TestMethod.

    0 讨论(0)
  • 2020-12-02 06:06

    While I agree with what everyone has said above. I have a different take on this code. Basically you're assigning the new list to the local variable myList not the global. if you change the signature of ChangeList(List myList) to private void ChangeList() you'll see the output of 3, 4.

    Here's my reasoning... Even though list is passed by reference, think of it as passing a pointer variable by value When you call ChangeList(myList) you're passing the pointer to (Global)myList. Now this is stored in the (local)myList variable. So now your (local)myList and (global)myList are pointing to the same list. Now you do a sort => it works because (local)myList is referencing the original (global)myList Next you create a new list and assign the pointer to that your (local)myList. But as soon as the function exits the (local)myList variable is destroyed. HTH

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-02 06:07

    C# just does a shallow copy when it passes by value unless the object in question executes ICloneable (which apparently the List class does not).

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

    If you change the values of the things your new List references, you change the original List also (since it is referencing the same objects). However, you then change what myList references entirely, to a new List, and now only the original List is referencing those integers.

    Read the Passing Reference-Type Parameters section from this MSDN article on "Passing Parameters" for more information.

    "How do I Clone a Generic List in C#" from StackOverflow talks about how to make a deep copy of a List.

    0 讨论(0)
  • 2020-12-02 06:08

    Initially, it can be represented graphically as follow:

    Init states

    Then, the sort is applied myList.Sort(); Sort collection

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

    Lost reference

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

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

    0 讨论(0)
  • 2020-12-02 06:16

    Use the ref keyword.

    Look at the definitive reference here to understand passing parameters.
    To be specific, look at this, to understand the behavior of the code.

    EDIT: Sort works on the same reference (that is passed by value) and hence the values are ordered. However, assigning a new instance to the parameter won't work because parameter is passed by value, unless you put ref.

    Putting ref lets you change the pointer to the reference to a new instance of List in your case. Without ref, you can work on the existing parameter, but can't make it point to something else.

    0 讨论(0)
  • 2020-12-02 06:28

    This link will help you in understanding pass by reference in C#. Basically,when an object of reference type is passed by value to an method, only methods which are available on that object can modify the contents of object.

    For example List.sort() method changes List contents but if you assign some other object to same variable, that assignment is local to that method. That is why myList remains unchanged.

    If we pass object of reference type by using ref keyword then we can assign some other object to same variable and that changes entire object itself.

    (Edit: this is the updated version of the documentation linked above.)

    0 讨论(0)
提交回复
热议问题