Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is pass by reference just a legacy?

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).

like image 945
Trent Avatar asked Sep 07 '15 07:09

Trent


1 Answers

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 structs when passing them around. Imagine you have a byte[] array representing a binary large object (BLOB), possibly a few megabytes in size value of some struct 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 reference.

    (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.

like image 100
stakx - no longer contributing Avatar answered Oct 20 '22 01:10

stakx - no longer contributing