Search code examples
c#ref-parameters

Passing and updating reference type parameters in function


Consider I have object A which is holding reference to B object type, but this time initilized to null.

A->B( == null)

I want to replace the null with object of type B which hold reference to type C.
(B->C).
So I will get A->B->C .

Why isn't it possible to link them by giving the reference of B object(which holds null but probably linked to specific memory address behind the scenes and assign to it the C object instead of null so afterward it will be A->B->C?

Why I must forward the A object for being able to do this manipulation?

This question is asked for trying to understand why in the following code: insertion of new node as a child of specific Node do not work. The code is :

public void InsertNodeToTreeLDR(TreeNode newNode)
        {
            var currRoot = Root;
            InsertNodeToTreeHelper(ref currRoot, newNode);           
        }

        private void InsertNodeToTreeHelper(ref TreeNode currTreeRoot, TreeNode newNode)
        {
            if (currTreeRoot == null)
            {
                currTreeRoot = newNode;
                return;
            }

            else if (newNode.Data.CompareTo(currTreeRoot.Data) >= 0)
            {
                var currRootLeftChild = currTreeRoot.Leftchild;
                InsertNodeToTreeHelper(ref currRootLeftChild, newNode);
            }

            else
            {
                var currRootRightChild = currTreeRoot.RightChild;
                InsertNodeToTreeHelper(ref currRootRightChild, newNode);
            }

        }

Note:
I didn't want to include all code here so, this function is part of Tree Class which hold root of type TreeNode.
Think that you already have Tree with root with data == 2 (int), and want to add new left child as with data == 1.
In my implementation the linking between the Node and its child do not work.


Solution

  • You seem to be confused about what passing by reference does and how that interacts with reference types in C#. This code does nothing:

    public void InsertNodeToTreeLDR(TreeNode newNode)
    {
        var currRoot = Root;
        InsertNodeToTreeHelper(ref currRoot, newNode);           
    }
    

    To see why it does nothing, let's step through this one line at a time.

    var currRoot = Root;
    

    This line defines a variable called currRoot that is then told to reference the same TreeNode that's referenced by Root. So now currRoot and Root are referring to the same TreeNode instance.

    InsertNodeToTreeHelper(ref currRoot, newNode);
    

    Here we're passing the variable currRoot by reference. This means that the InsertNodeToTreeHelper method is allowed to modify the value of currRoot. But remember that the value of currRoot is a reference to a TreeNode, so if the value of currRoot is modified, you're simply telling that specific variable to point somewhere else, it won't do anything to the value of Root (which is also a reference to some TreeNode instance).

    If that's not clear, let me try to illustrate this with a simpler example:

    public void ClearTree()
    {
        var currRoot = Root;
        ClearTreeHelper(ref currRoot);           
    }
    
    private void ClearTreeHelper(ref TreeNode currTreeRoot)
    {
        currTreeRoot = null;
    }
    

    This code example is really the same as just writing this:

    public void ClearTree()
    {
        var currRoot = Root;
        // ClearTreeHelper       
        currRoot = null;  
    }
    

    Hopefully this makes it more clear why your pass by reference doesn't do anything.

    Now, for your actual problem, as best I can guess, what you actually want is something like this:

    public void InsertNodeToTreeLDR(TreeNode newNode)
    {
        if( Root == null )
        {
            Root = newNode;
            return;
        }
    
        InsertNodeToTreeHelper( Root, newNode );           
    }
    
    private void InsertNodeToTreeHelper(TreeNode root, TreeNode newNode)
    {
        if (newNode.Data.CompareTo(root.Data) >= 0)
        {
            if( root.LeftChild == null )
            {
                root.LeftChild = newNode;
            }
            else
            {
                InsertNodeToTreeHelper( root.LeftChild, newNode);
            }
        }
        else
        {
            if( root.RightChild == null )
            {
                root.RightChild = newNode;
            }
            else
            {
                InsertNodeToTreeHelper( root.RightChild, newNode);
            }
        }
    }
    

    This can also be done without recursion (which I would recommend, I think it would simplify the code immensely and remove the need for a helper method).