Perhaps this is a bit naive of me, but I can't really seem to find/think of a decent use-case for "pass by reference". Changing an immutable string (as some other Q/As have mentioned) is generally avoidable and returning multiple variables is generally better handled by returning a Tuple, List, array, etc.
The example on MSDN is terrible in my opinion; I would simply be returning a value in the Square
method, instead of having it declared as void
.
It seems to me like it's a bit of a legacy part of C#, rather than an integral part of it. Can someone smarter than me try to explain why it's still around and/or some real-world use-cases that are actually practical (i.e. Changing an immutable string is avoidable in almost every case).
P.S.: I followed up on some of the comments by @KallDrexx and @newacct. I see now that they were right and I was wrong: my answer was somewhat misleading. The excellent article "Java is pass-by-value, dammit!" by Scott Stanchfield (Java-specific, but still mostly relevant to C#) finally convinced me so.
I'll leave the misleading bits of my answer striked through for now, but might later remove them.
Pass by reference is not just used with ref
or out
parameters. More importantly, all reference types are passed by reference (thus their name), although this happens transparently.
Here are three frequent use cases for pass-by-reference:
Prevent copying of large struct
s when passing them around. Imagine you have a value of some byte[]
array representing a binary large object (BLOB), possibly a few megabytes in sizestruct
type that contains lots of fields. A value of that type might potentially occupy quite a lot of memory. Now you want to pass this value to some method. Do you really want to pass it by value, i.e. create a temporary copy?
You can avoid unnecessary copying of large structs by passing them by ref
erence.
(Luckily for us, arrays such as byte[]
are reference types, so the array's contents are already passed by refence.)
It is often suggested (e.g. in Microsoft's Framework Design Guidelines) that types having value-type semantics should be implemented as reference types if they exceed a certain size (32 bytes), so this use case should not be very frequent.
Mutability. If you want a method to be able to mutate a struct
value that is passed to it, and you want the caller to observe the mutation of his version of that object, then you need pass by reference (ref
). If the value is passed to the method by value, it receives a copy; mutating the copy will leave the original object unmodified.
This point is also mentioned in the Framework Design Guideline article linked to above.
Note the widespread recommendation against mutable value types (See e.g. "Why are mutable structs evil?"). You should rarely have to use ref
or out
parameters together with value types.
COM interop as mentioned in this answer often requires you to declare ref
and out
parameters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With