Reputation: 2307
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);
}
}
Upvotes: 0
Views: 139
Reputation: 16628
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));
}
}
}
Upvotes: 1
Reputation: 66389
What you're looking for is pointers, and C# doesn't expose them - luckily.
You can simply assign the values back to the class variable:
operation(ref container[parentIndex], ref leftChild, ref rightChild);
container[leftChildIndex] = leftChild;
container[rightChildIndex] = rightChild;
Upvotes: 1