Do we really need to use REF and OUT while coding in Unity?


I understand what “ref” and “out” do, but I’m wondering whether I really need to use them.
Let’s say that I have two variables declared in the beginning of the script:

int i = 1;
int j = 2;

And I want to swap these values so that “i” would be equal to 2 and “j” - to 1.

And that’s where I start struggling if I need to use ref, since I can refer to these variables directly:

void Swap () {
    int temp = i;
    i = j;
    j = temp;

So far I used ref’s just to be able to understand which variables I’m dealing with…

To summarize - is there a particular reason to use REF and OUT since we can always get access to the variables that were already declared?

The short answer: yes, occasionally.

The long answer:
REF and OUT are used to point to the same memory location as the original variable. The difference being, that OUT requires an uninitialized variable, and REF takes an initialized variable.

Why would we need to use them? Consider the case with raycasting: It takes a RaycastHit struct. Structs are not reference types, so all values contained in a struct will be copied over to the called method as local variables. Without the OUT keyword, we would only copy the (uninitialized values of the) uninitialized struct to the raycast, and get noting back, because the raycast would modify a COPY of the struct we passed to it. With the OUT keyword, we pass the memory location of the struct to the raycast method, so any change made to the struct within the raycast will be retained when execution leaves the raycast method. They are sort of similar to pointers in C++, with a few caveats.

So it makes sense to use OUT and REF with structs because they’re not reference types. How about actual reference types; classes? We’re passing a reference to the object, so any change made to the object will be reflected in it to everyone who has the same reference. We don’t need REF or OUT for that. What we do need REF or OUT with reference types is, if we want to change the reference. Consider this case:

public void ClearList(List<int> aList){
    aList = new List<int>();

public void ClearList(ref List<int> aList){
    aList = new List<int>();

List<int> anotherList = new List<int>();
Debug.Log(anotherList.Count); // prints 1
ClearList(ref anotherList);
Debug.Log(anotherList.Count) // prints 0

This is because instead of a reference, we pass the actual memory location. This could be thought of as passing the real reference (ref) versus a copied reference (without ref). If you change a copy of the reference, the caller will be none the wiser, even if you change it. If you change the same reference that the caller uses (passed with ref) then, obviously, the reference of the caller will also change.

An analogy: Imagine a house. The owner has no memory and has the address of this house on a card (the reference). If our owner copies the address to a different card and gives that to his friend (calling method without ref), no matter what the friend does to his card, the address on the owner’s card will not change. When the owner gives his card to the friend (calling method with ref) and the friend changes the address, our owner will no longer be able to find his house.

C# is a real language – not made just for Unity or just for games – and has a lot of features. Many are alternate ways of doing the same thing. Some are to solve very specific weirdness that you won’t get in something as small as a game. There’s no special reason to learn or use every single language thingy.

But it turns out that “pass by reference” is a standard, essential language feature. C# happens to use REF to do it. Other languages do it differently. It’s one of those things that you never really understand until you have a problem that needs it. But then you can immediately see why we invented return-by-ref. Even so, I use it maybe once every 10,000 lines.