Search code examples
c#delegatesref

How can I use ref to modify this class variable in C#?


I'm trying to use the ref keyword in C# to modify a class variable passed to a delegate function. I want the delegate function to be able to modify the values stored in container for the parent and its two children. What happens right now is that a delegate function can modify the parent (since I pass a reference directly to container[parent]) but not the children, since I have to process them first and thus pass a reference to leftChild and rightChild.

  • Is it possible to have leftChild be a reference to container[leftChildIndex], so that the delegate function can modify the value stored in container? (same with right child)

    private void traversePostOrder(Modify operation, int parentIndex) {
        if (parentIndex < size) {
            int leftChildIndex = getLeftChildIndex(parentIndex);
            int rightChildIndex = getRightChildIndex(parentIndex);
            T parent = container[parentIndex];
            T leftChild = default(T);
            T rightChild = default(T);
    
            Library.Diagnostics.Message.logMessage("P: " + parent, 2);
    
            if (leftChildIndex < container.Length) {
                traversePostOrder(operation, leftChildIndex);
                leftChild = container[leftChildIndex];
            }
    
            if (rightChildIndex < container.Length) {
                traversePostOrder(operation, rightChildIndex);
                rightChild = container[rightChildIndex];
            }
    
            operation(ref container[parentIndex], ref leftChild, ref rightChild);
        }
    }
    

Solution

  • The problem is where you define them:

    T leftChild = default(T);
    T rightChild = default(T);
    

    You pass a reference to those objects, and they get destroyed right after the end of the method because they're local variables.
    Try sending the objects directly.

    private void traversePostOrder(Modify operation, int parentIndex) {
        if (parentIndex < size) {
            int leftChildIndex = getLeftChildIndex(parentIndex);
            int rightChildIndex = getRightChildIndex(parentIndex);
            T parent = container[parentIndex];
            bool leftChildModified = false;
            bool rightChildModified = false;
    
            Library.Diagnostics.Message.logMessage("P: " + parent, 2);
    
            if (leftChildIndex < container.Length) {
                traversePostOrder(operation, leftChildIndex);
                leftChildModified = true;
            }
    
            if (rightChildIndex < container.Length) {
                traversePostOrder(operation, rightChildIndex);
                rightChildModified = true;
            }
    
            if(leftChildModified && rightChildModified)
            {
                operation(ref container[parentIndex], ref container[leftChildIndex], ref container[rightChildIndex]);
            }
            else if(leftChildModified)
            {
                operation(ref container[parentIndex], ref container[leftChildIndex], ref Default(T));
            }
            else if(rightChildModified)
            {
                operation(ref container[parentIndex], ref Default(T), ref container[rightChildIndex]);
            }
            else
            {
                operation(ref container[parentIndex], ref default(T), ref default(T));
            }
        }
    }