What is the difference between ref and out in runtime?

by Gábor Angyal   Last Updated July 11, 2019 19:05 PM

C# provides the ref and the out keyword to make arguments to be passed by reference. The semantic of the two is very similar. The only difference is in the initialization of the flaged variable:

  • ref requires the variable to be initialized before passing it to the function, out does not.
  • out requires the variable to be initialized inside the function, ref does not.

The use cases of these two keywords are also almost the same, and their too frequent usage is I beleive considered a code smell (although there are valid use cases like the TryParse and TryGetValue patterns).

Because of this could someone explain, why there are two very similar tools in C# for so narrow use cases?

Also, on MSDN, it is stated that they have different run-time behavior:

Although the ref and out keywords cause different run-time behavior, they are not considered part of the method signature at compile time.

How is their run-time behavior different?

Conclusion

Both answers looks correct, thank you both. I accepted jmoreno's because it is more explicit.



Answers 3


here's an interesting writeup on the topic that may answer your question:

http://www.dotnetperls.com/ref

point of interest:

"The difference between ref and out is not in the Common Language Runtime, but is in the C# language itself."

update:

the senior developer at my work just corroborated @jmoreno's answer, so make sure you read it!.

Dan Beaulieu
Dan Beaulieu
February 10, 2015 13:08 PM

At the time this question was asked, the MSDN article was subtly incorrect (it has since been corrected). Instead of "cause different behavior" it should be "requires different behavior".

In particular, the compiler enforces different requirements for the two keywords, even though the same mecanism (IL) is used to enable the behavior.

jmoreno
jmoreno
February 10, 2015 15:34 PM

Runtime? Absolutely none. You can't overload a method with the same parameters differing only by ref or out keyword.

Try to compile this and you'll get a compile error "Method with same signature is already declared":

    private class MyClass
    {
        private void DoSomething(out int param)
        {
        }
        private void DoSomething(ref int param)
        {
        }
    }

To answer this question: "...why there are two very similar tools in C# for so narrow use cases?"

From a code readability and API standpoint there is a huge difference. As a consumer of the API I know that when "out" is used the API does not depend on the out parameter. As the API developer I prefer the "out" and use "ref" only when absolutely (RARELY!) necessary. See this reference for a great discussion:

https://stackoverflow.com/questions/1516876/when-to-use-ref-vs-out

Supporting info: I compiled the following method and disassembled it. I used the ref and out keywords (out in this example), but the assembly code did not change except for an address reference as I would expect:

    private class MyClass
    {
        internal void DoSomething(out int param)
        {
            param = 0;
        }
    }

00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,34h
00000009 xor eax,eax
0000000b mov dword ptr [ebp-10h],eax
0000000e mov dword ptr [ebp-1Ch],eax
00000011 mov dword ptr [ebp-3Ch],ecx
00000014 mov dword ptr [ebp-40h],edx
00000017 cmp dword ptr ds:[008B1710h],0
0000001e je 00000025
00000020 call 6E6B601E
00000025 nop
param = 0;
00000026 mov eax,dword ptr [ebp-40h]
00000029 xor edx,edx
0000002b mov dword ptr [eax],edx
}
0000002d nop
0000002e lea esp,[ebp-0Ch]
00000031 pop ebx
00000032 pop esi
00000033 pop edi
00000034 pop ebp
00000035 ret

Am I reading the assembly correctly?

Shmoken
Shmoken
February 12, 2015 01:20 AM

Related Questions


Updated August 22, 2015 19:02 PM

Updated April 14, 2016 08:02 AM

Updated October 06, 2017 15:05 PM

Updated June 13, 2015 02:02 AM

Updated May 13, 2015 21:02 PM