Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by Neitrosha · Mar 04, 2014 at 11:16 PM · c#outref

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

Hi!

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?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
6

Answer by Jamora · Mar 04, 2014 at 11:40 PM

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>();
 anotherList.Add(1);
 ClearList(anotherList);
 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.

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Neitrosha · Mar 05, 2014 at 12:20 AM 0
Share

Thank you for this great explanation!

As for your code examples, there is one issue I'm still wondering about:

Why would we need to pass a ref variable into the function since we can refer to the List directly?

Like,

  List<int> anotherList = new List<int>();
     anotherList.Add(1);
 
 public void ClearList(){
     anotherList.Clear ()
 }

We will still get the list cleared.

I understand what REF and OUT are used for, but in this particular case they are not needed except for the case we want the function's declaration to be clear enough to understand what's it for and which variables it needs.

avatar image Neitrosha · Mar 05, 2014 at 12:41 AM 0
Share

Thank you) Now I get it.

avatar image Jamora · Mar 05, 2014 at 12:54 AM 1
Share

Clearing a list is a bit silly usage of REF, I admit, but it was the first one that popped to $$anonymous$$d.

The point is, REF and OUT are useful when returning more than one value type from a method, or when operating directly on the reference of an object.

 public void DivAnd$$anonymous$$od(int divident, int divisor, ref int quotient, ref int remainder){
 quotient = dividend/divisor;
 remainder = dividend%divisor;
 }
 
 int quotient, remainder = 0;
 DivAnd$$anonymous$$od(5,2,ref quotient, ref remainder);
 Debug.Log(quotient+" "+remainder); //outputs: 2 1

We can also take advantage of the REF with the strategy pattern. Consider this:

 public abstract class Strategy{
     public abstract int Operate(int a, int b);
 
     public bool SwitchStrategy(ref oldStrategy){
         if(oldStrategy is AddititionStrategy){
             oldStrategy = new SubtractionStrategy();
             return true;
         }else{
             oldStrategy = new AdditionStrategy();
             return false;
         }
     }
 }
 
 public class AdditionStrategy : Strategy{
     public override int Operate(int a, int b){ return a+b; }
 }
 
 public class SubtractionStrategy : Strategy{
     public override int Operate(int a, int b){ return a-b; }
 }

Now, the user can call currentStrategy.SwitchStrategy(ref currentStrategy); without even knowing which strategy he is using. If he wants to know which one he got, he checks the bool.

avatar image Quintinium · Jul 11, 2017 at 06:57 PM 0
Share

That is possibly the best explanation of the difference between passing by reference versus a copy. Although, I wish you would have explained the case of using out in the case of an uninitialized variable. If it is not initialized, then what is there to pass? I can only assume that the variable would be being passed with a value associated with it's address.

This is my code in question. (which it works fine, I'm just unclear about how it's working)


 if (!Camera.main)
             return; 
         RaycastHit hit; 
         if (Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit, 25.0f, Layer$$anonymous$$ask.Get$$anonymous$$ask ("ChessPlane"))) {
             selectionX = (int)hit.point.x; 
             selectionY = (int)hit.point.z;
         }

======= RaycastHit hit is an uninitialized variable. $$anonymous$$y assumption is it is passing the real time location of the RaycastHit hit's virtual location, but without being initialized...how does that work? What does out provide? (I think I may be understanding this a bit even as I type, but I don't trust it, so any reply would be appreciated.)

This maybe less of a Unity question, and more of a general c# question, but I suspect the keyword out may be Unity exclusive. I'm just not sure. Thank you

avatar image Owen-Reynolds Quintinium · Jul 11, 2017 at 09:14 PM 0
Share

out is standard C#. It's a $$anonymous$$or variation of `ref'. The remark about it requiring an uninitialized variable isn't true. It can be used with an uninitialized variable. $$anonymous$$y longer explanation is at taxesforcatses-dot-com/bookW/ch23refParms.pdf in section 2. But any C# book probably has one just as good.

avatar image Jwizard93 Quintinium · Jul 11, 2017 at 09:16 PM 0
Share

Don't quote me but i think the compiler just needs to see the declaration so it knows the intended type for the rest of the calling function. It will be initialized in the callee function. Which is why it requires you to initialize all out variables in the callee before it will compile.

avatar image Jwizard93 Jwizard93 · Jul 11, 2017 at 09:17 PM 0
Share

What I guess I am saying is that when it compiles the calling function it wants to be able to do that without having to compile the callee just yet.

avatar image
1

Answer by Owen-Reynolds · Mar 05, 2014 at 01:12 AM

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.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

24 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Store a reference to a variable instead of just the value in a class? 1 Answer

Help with using 3D code for a 2D game.(It's probably an easy fix) 1 Answer

Space Shooter Mobile Touch Controls Issue 1 Answer

Unity IOS Build Error: AssemblyResolutionException: Failed to resolve assembly: 'UnityEngine.CoreModule 0 Answers

I want to spawn objects probabilistically. 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges