When to use pass-by-value vs. pass-by-reference?

I have a co-worker that uses pass by reference on most parameters for most method calls (between DAL / BLL for example, SqlConnection object to a common method that creates an open a connection, or even among methods in the same class).

Does this provide an advantage or is this incorrect usage? (i.e. When should I use either one method vs. the other and why?)

(I do know usage with strings does not work with ref params.)

Who is Participating?
jamesrhConnect With a Mentor Commented:
There is a tiny preformance advantage in passing by reference in .NET however the price you pay for this is high in terms of the exposure of the original data.  If you are going to pass everything by reference you might as well make everything a "global" variable.  There is also very often a misunderstanding with respect to passing reference variables in .NET.  All reference variables are functionally pointers, so when you pass by value (the default behavior) you are only making a copy of the pointer (essentially a 32 or 64 bit integer), you are not making a copy of the whole class.  So for classes even pass by value is in essence pass by reference in terms of the concept as implemented in most OOP languages.  In other words, when you pass an object by "value" you are not copying the object only the pointer and so changes made to the referenced object within the called method affect the "original" object.  All that the ref keyword gives you for reference types in .NET is the ability to change the object that the original object variable is pointing to.  Unless you actually need to make this object swap you are gaining very little and providing an opportunity for unexpected results.  Very often this habit comes into play with programmers transitioning from other OOP languages, especially C++ where pass by value means actually making a copy of the object itself.
käµfm³d 👽Commented:
Pass by ref and value aren't as big of an issue in .NET as they are in C/C++. I believe everything in .NET is passed by value--value types create copies of the data and reference types create copies of the pointer. When passing an initialized ref type to a function, you have access to the objects members for modification because you are working with a pointer to the original data. Where you run into trouble is if you were to pass a ref type to a function that at some point during execution called "new". The new memory would be allocated, but the COPY of the pointer would hold the reference--not the original pointer. In order to call new within a function and have the original pointer maintain a reference to the new data, you have to use either the "ref" or "out" keywords, which have the effect of pass by ref.
Passing parameter by ref makes sense only for value types.
Reason: Value types stored on the thread's stack. When value type (Int32, Double, any struct, etc) passed to the method, value type object copy made and passed to method. You can see this by changing parameter inside method - all changes will not affect original object. Reference types are passed by default by reference.

So, there are two ways I see to use ref:
1) you have some big value type object, you can pass it by ref to speed up method call and save stack memory
2) you want to change original value type object inside called method

I don't like both :)
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

If you make the assumption that the language has been well-designed, and in particular that care has been taken in designing the parameter and result passing mechanisms, they you should trust the designers and use the default mechanism unless you have a good reason to do otherwise.  There is thus an important clue in the fact that you must explicitly specify ref if you want to pass by ref and you must do so in both the method declaration and the method call.

Suppose you have something like
void f(c) { ... c += 1; ...}
void g() { int k = 5; ... f(k); ... }
If you really want f to change k, then you would pass k by reference.

Because structs are value types, they are copied when they are passed by value (the default).  If you had a large struct, you would see some performance benefit if you passed it by reference, especially if you did so often. However, you would also lose the safety granted by passing by value because and method you called would be able to modify the original copy of your struct.

In summary, pass by value unless you have a good reason to do otherwise.  "Always" is not a good reason; it's lazy.
devo00Author Commented:
Fantastic answers guys, sorry, I just couldn't pick one, the first put it nicely in layman's terms (which I needed), and the latter will fill me in on what the heck is going on.
All Courses

From novice to tech pro — start learning today.