0

I am using ref so that it changes the root of the Binary Search Tree I am trying to create, however, it's not working the way I intend for it to.

    public BinaryNode<T> Root { get; set; }
    public BinaryTree() : base()
    {
        Root = null;

    public T Insert(ref BinaryNode<T> root, T val)
    {
        // Insert here
        if (root == null)
        {
            BinaryNode<T> newNode = new BinaryNode<T>(val);
            root = newNode;
            Size++;
            return val;
        }

        if (val.CompareTo(root.Data) < 0)
        {
            BinaryNode<T> left = root.LeftChild;
            return Insert(ref left, val);
        }

        else if (val.CompareTo(root.Data) > 0)
        {
            BinaryNode<T> right = root.RightChild;
            return Insert(ref right, val);
        }

        return val;
    }

    public override T Insert(T val)
    {
        BinaryNode<T> root = Root;
        return Insert(ref root, val);
    }

I was expecting that when I do root = newNode that for example Root would change during the first insert. However, this is not the case. Root stays null even after. I am suspecting that this is something more related to properties and how it interacts with ref instead of ref itself?

1 Answers1

3

You are modifying the local root variable since that's the reference you are passing in. If you want this to work you need to then assign it back to the Root property like so:

public T Insert(T val)
{
    BinaryNode<T> root = Root;
    var result = Insert(ref root, val);

    Root = root;
    return result;
}

Perhaps a cleaner option would be to directly use a backing field for the property like so:

BinaryNode<T> _root;
public BinaryNode<T> Root
{
    get { return _root; }
    set { _root = value; }
}

public T Insert(T val)
{
    return Insert(ref _root, val);
}
Fredy Treboux
  • 3,167
  • 2
  • 26
  • 32
  • Good point can you also explain why is that the case for reference types – Mrinal Kamboj Oct 09 '16 at 17:14
  • I was thinking that creating a backing field for the property would solve it, but I read that if there is no special logic in the get/set to just use auto-properties. But it seems like there lies problems when used with ref trying to change the hidden field. –  Oct 09 '16 at 17:19
  • Also, the problem with assigning `Root = root` is that if I insert anything after the root, like multiple insertions, would that not just change the Root every single time? –  Oct 09 '16 at 17:20
  • This would be the same with value types. The problem with the property, is that even though you know you're just encapsulating a hidden field the property is basically sintactic-sugar over setter and getter methods and the "ref" keyword expects a variable to use as reference. You can see in-depth discussion regarding this in the follwoing question: http://stackoverflow.com/questions/4518956/a-property-or-indexer-may-not-be-passed-as-an-out-or-ref-parameter – Fredy Treboux Oct 09 '16 at 17:22
  • It will only change the Root property if you are modyfing the "root" variable/argument inside your Insert(ref BinaryNode, T) method. – Fredy Treboux Oct 09 '16 at 17:25
  • Of course in the first example where you pass in a local copy `root`, the property will not be affected until after the method has ___completed___ and you assign back to the property setter. In the other case where you use the backing field `_root`, the property is affected as soon as the still running method assigns to the `ref` argument. This might make a difference in some uses. – Jeppe Stig Nielsen Oct 09 '16 at 17:48