I'm trying to figure out how to reproduce the behaviour of ref
modifier in C#.
I have two methods:
static void Foo(ref int x)
{
x = 25;
}
unsafe static void Foo(int* x)
{
*x = 25;
}
Even though the generated IL codes for these two method are the same, the signatures are different:
The code for Foo(ref int)
:
.method private hidebysig static void Foo(int32& x) cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 25
IL_0004: stind.i4
IL_0005: ret
} // end of method Program::Foo
And the code for Foo(int*)
.method private hidebysig static void Foo(int32* x) cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 25
IL_0004: stind.i4
IL_0005: ret
} // end of method Program::Foo
So my question is, why the signatures are different while the generated codes are same? Can't the same work be performed using pointers?
Note: I compiled this code Visual Studio 2015 Preview
, Debug Mode
.
The reason the two methods have the same IL for their implementation is that the stind.i4
opcode:
stores an int32 value at the supplied address (type native int, *, or &).
This means that OpCode works for both a pointer and a reference, since they are both effectively just addresses to the storage location. Since the work being done is identical other than the type being passed in, but the same OpCode applies, the method bodies end up being identical.
This does not mean they are interchangable methods, however. They require calling in different manners, which is why the signatures differ. Also, this is just the intermediate language - they will likely get compiled to machine code differently by the JIT.