简体   繁体   中英

C# reference clarification

A few days back I came into an interesting thing, but I can't wrap my head around it, or let's say I have a feeling what is happening, but I'm not sure.

Having the following linked list implementation:

public class LinkedList<T>
{
    private class Node
    {
        public T Value;
        public Node? Next;
        public Node(T value) => (Next, Value) = (null, value);
    }

    private Node? head;

    public LinkedList()
    {
        head = null;
    }
    public void InsertBack1(T value)
    {
        if (head == null)
        {
            head = new Node(value);
        }
        else
        {
            Node? current = head;
            while (current?.Next != null)
            {
                current = current.Next;
            }
            current.Next = new Node(value); ;
        }
    }

    public void InsertBack2(T value)
    {
        Node? current = head;
        while (current != null)
        {
            current = current.Next;
        }
        current = new Node(value);
    }

    public void Print()
    {
        var current = head;
        while (current != null)
        {
            Console.Write(current.Value + " --> ");
            current = current.Next;
        }
    }
}

By using the InsertBack1() method, the insertion works just fine, however the InsertBack2() method does not. Using the following snippet:

var list = new LinkedList<int>();
list.InsertBack1(1);
list.InsertBack1(2);
list.InsertBack2(3);

I get the following linked list: 1 -> 2.

In the InsertBack2() method, the code checks whether the current node is null or not, if it's not, moves the current reference to the child or creates a new node for the corresponding element. In theory it should be fine, but while running the new node is not inserted. As I understand, when the current is moved to an uninitialized child, it somehow looses all reference from the head object and goes out of sync (let's say so).

In the InsertBack1() method however it just works, the current object gets a new child and the head object receives the modifications as well.

So what is happening here exactly with the references?

Let's see what happens when you call InsertBack2(3) .

public void InsertBack2(T value)
    {
        Node? current = head; // current now points to node 1
        while (current != null)
        {
            // current is not null, so try next
            current = current.Next;
        }
        // The above loop will execute two times, after which current points to  null (which is the termination criteria for the loop)
        current = new Node(value); // Now current is null and we assign a new instance. 
    }

See my comments above. After the last line, current contains the new node, but since it's a local variable, it just runs out of scope and is forgotten. That node is never added to the list. A similar implementation would work, if the method InsertBack3() would be a method of Node , but that gets a quite different data structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM