I'm curious about how C# behaves when passing value/reference types into a method. I'd like to pass a boxed value type into the method "AddThree". The idea is to get in the caller function (Main) the result of the operations performed within "AddThree".
static void Main(string[] args)
{
int age = 3;
object myBox = age;
AddThree(myBox);
// here myBox = 3 but I was expecting to be = 6
}
private static void AddThree(object age2)
{
age2 = (int)age2 + 3;
}
I've tried this with pure reference types like string and I get the same result. If I "wrap" my int within a class and I use the "wrap" class in this example it works as I'm expecting, ie, I get myBox = 6. If I modify "AddThree" method signature to pass the parameter by ref, this also returns 6. But, I don't want to modify the signature or create a wrapper class, I want to just box the value.
I don't want to modify the signature or create a wrapper class, I want to just box the value.
Then that will be a problem. Your method passes a boxed int
, then unboxes it and adds 3 to the local age2
, which causes another boxing operation, and then throws away the value. De-facto, you're assinging age2
to two different objects on the heap, they do not point to the same object.
Without modifying the method signature, this won't be possible.
If you look at the generated IL for AddThree
, you'll see this clearly:
AddThree:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: unbox.any System.Int32 // unbox age2
IL_0007: ldc.i4.3 // load 3
IL_0008: add // add the two together
IL_0009: box System.Int32 // box the result
IL_000E: starg.s 00
IL_0010: ret
You unbox the value, add 3 and then box the value again, but you never return it.
To visualize this case further, try returning the newly boxed value from the method (just for the sake of the test), and use object.ReferenceEquals
to compare them both:
static void Main(string[] args)
{
int age = 3;
object myBox = age;
var otherBox = AddThree(myBox);
Console.WriteLine(object.ReferenceEquals(otherBox, myBox)); // False
}
private static object AddThree(object age2)
{
age2 = (int)age2 + 3;
return age2;
}