In C#, the parameters to a method can be either reference types or value types. When passing reference types, a copy of the reference is passed. This way, if inside a method we try to reassign the passed reference to another object instance, outside of the method the reassignment is not visible.
To make this working, C# has the ref modifier. Passing a reference type with ref actually uses the original reference instead of a copy. (Correct me if I'm wrong).
In this case, since we are not creating a copy of the reference, are we saving any memory? If a method is extensively called, does this improve the overall performance of the application?
Thanks!
No, it doesn't. If anything, it's slower because of the extra lookup.
There's no reason to pass a reference type by reference unless you specifically intend to assign to it later.
Since some people seem to think that the compiler passes "the variable itself", take a look at the disassembly of this code:
using System;
static class Program
{
static void Test(ref object o) { GC.KeepAlive(o); }
static void Main(string[] args)
{
object temp = args;
Test(ref temp);
}
}
which is (on x86, for simplicity):
// Main():
// Set up the stack
00000000 push ebp // Save the base pointer
00000001 mov ebp,esp // Set up stack pointer
00000003 sub esp,8 // Reserve space for local variables
00000006 xor eax,eax // Zero out the EAX register
// Copy the object reference to the local variable `temp` (I /think/)
00000008 mov dword ptr [ebp-4],eax // Copy its content to memory (temp)
0000000b mov dword ptr [ebp-8],ecx // Copy ECX (where'd it come from??)
0000000e cmp dword ptr ds:[00318D5Ch],0 // Compare this against zero
00000015 je 0000001C // Jump if it was null (?)
00000017 call 6F910029 // (Calls some internal method, idk)
// THIS is where our code finally starts running
0000001c mov eax,dword ptr [ebp-8] // Copy the reference to register
0000001f mov dword ptr [ebp-4],eax // ** COPY it AGAIN to memory
00000022 lea ecx,[ebp-4] // ** Take the ADDRESS of the copy
00000025 call dword ptr ds:[00319734h] // Call the method
// We're done with the call
0000002b nop // Do nothing (breakpoint helper)
0000002c mov esp,ebp // Restore stack
0000002e pop ebp // Epilogue
0000002f ret // Return
This was from an optimized compilation of the code. Clearly, there's an address of a variable being passed, and not "the variable itself".