What's the difference between the 'ref' and 'out' keywords?

405,955

Solution 1

ref tells the compiler that the object is initialized before entering the function, while out tells the compiler that the object will be initialized inside the function.

So while ref is two-ways, out is out-only.

Solution 2

The ref modifier means that:

  1. The value is already set and
  2. The method can read and modify it.

The out modifier means that:

  1. The Value isn't set and can't be read by the method until it is set.
  2. The method must set it before returning.

Solution 3

Let's say Dom shows up at Peter's cubicle about the memo about the TPS reports.

If Dom were a ref argument, he would have a printed copy of the memo.

If Dom were an out argument, he'd make Peter print a new copy of the memo for him to take with him.

Solution 4

I am going to try my hand at an explanation:

I think we understand how the value types work right? Value types are (int, long, struct etc.). When you send them in to a function without a ref command it COPIES the data. Anything you do to that data in the function only affects the copy, not the original. The ref command sends the ACTUAL data and any changes will affect the data outside the function.

Ok on to the confusing part, reference types:

Lets create a reference type:

List<string> someobject = new List<string>()

When you new up someobject, two parts are created:

  1. The block of memory that holds data for someobject.
  2. A reference (pointer) to that block of data.

Now when you send in someobject into a method without ref it COPIES the reference pointer, NOT the data. So you now have this:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Two references pointing to the same object. If you modify a property on someobject using reference2 it will affect the same data pointed to by reference1.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

If you null out reference2 or point it to new data it will not affect reference1 nor the data reference1 points to.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Now what happens when you send someobject by ref to a method? The actual reference to someobject gets sent to the method. So you now have only one reference to the data:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

But what does this mean? It acts exactly the same as sending someobject not by ref except for two main thing:

1) When you null out the reference inside the method it will null the one outside the method.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) You can now point the reference to a completely different data location and the reference outside the function will now point to the new data location.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

Solution 5

ref is in and out.

You should use out in preference wherever it suffices for your requirements.

Share:
405,955
TK.
Author by

TK.

--

Updated on July 08, 2022

Comments

  • TK.
    TK. almost 2 years

    I'm creating a function where I need to pass an object so that it can be modified by the function. What is the difference between:

    public void myFunction(ref MyClass someClass)
    

    and

    public void myFunction(out MyClass someClass)
    

    Which should I use and why?

  • Daniel Earwicker
    Daniel Earwicker over 15 years
    Another cool thing specific to out is that the function has to assign to the out parameter. It's not allowed to leave it unassigned.
  • Paul Mitchell
    Paul Mitchell over 15 years
    Exactly. So it's not strictly true to say "Since you're passing in a reference type (a class) there is no need use ref".
  • mmmmmmmm
    mmmmmmmm over 15 years
    In theory it is right to say so because he wrote "so that it can be modified" which isn't possible on strings. But because of immutable objects "ref" and "out" are very useful also for reference types! (.Net contains a lot of immutable classes!)
  • etsuba
    etsuba over 15 years
    This works only if no new object is created and returned. When a new object is created, the reference to the old object would be lost.
  • Albic
    Albic over 15 years
    Yes, you're right. I didn't think of immutable objects like strings because most object are mutable.
  • faulty
    faulty over 15 years
    is 'ref' only applicable to value type? Since reference type is always pass by ref.
  • Rune Grimstad
    Rune Grimstad over 15 years
    Yes. Value types including structs
  • thr
    thr about 14 years
    @faulty: No, ref is not only applicable to value types. ref/out are like pointers in C/C++, they deal with the memory location of the object (indirectly in C#) instead of the direct object.
  • kenny
    kenny about 14 years
    not quite, as the accepted answer ref if directional and useless ignoring value-types if not passed back out.
  • Raymond
    Raymond about 14 years
    @kenny: Can you clarify a bit please - i.e., which words would you change to maintain the spirit of the answer but remove the inacuracy you percieve? My answer is not a crazy guess from a newbie, but the haste (terseness, typos) in your comment seems to assume it is. The aim is to provide a way of thinking about the difference with the least number of words.
  • Raymond
    Raymond about 14 years
    (BTW I'm familiar with value types, reference types, passing by reference, passing by value, COM and C++ should you find it useful to make reference to those concepts in your clarification)
  • kenny
    kenny about 14 years
    I don't disagree, but only a minor nit with 'ref' only for input. I have 2 points. 1 objects are passed by reference always. And the second point is that you only would add a reference if you care what happens in side the method or it has side effects for the caller. I think maybe I misread your answer in the context of the question, I read it as 'ref' is for in and 'out' is for out.
  • JasonTrue
    JasonTrue about 14 years
    @faulty: Counterintuitively, Reference types are always passed by value in C#, unless you use the ref specifier. If you set myval=somenewval, the effect is only in that function scope. The ref keyword would allow you to change myval to point to somenewval.
  • Dr. Wily's Apprentice
    Dr. Wily's Apprentice over 13 years
    This answer most clearly and concisely explains the restrictions that the compiler imposes when using the out keyword as opposed to the ref keyword.
  • Keith
    Keith over 13 years
    This is wrong - try the following: add someObject = null to Bar end execute. Your code will run fine as only Bar's reference to the instance was nulled. Now change Bar to Bar(ref MyClass someObject) and execute again - you'll get a NullReferenceException because Foo's reference to the instance has been nulled too.
  • Deebster
    Deebster almost 13 years
    ref Dom would have written the report in pencil so that Peter could modify it
  • Michael Blackburn
    Michael Blackburn almost 13 years
    @Deebster you know, that metaphor never did anything to you, why must you torture it so? ;)
  • Don Kirkby
    Don Kirkby over 12 years
    Welcome to Stack Overflow, Edwin. Strings are passed by reference, just like any other object, as far as I know. You may be confused because strings are immutable objects, so it's not as obvious that they are passed by reference. Imagine that string had a method called Capitalize() that would change the contents of the string to capital letters. If you then replaced your line a = "testing"; with a.Capitalize();, then your output would be "HELLO", not "Hello". One of the advantages of immutable types is that you can pass around references and not worry about other code changing the value.
  • supercat
    supercat over 12 years
    There are three fundamental types of semantics a type can expose: mutable reference semantics, mutable value semantics, and immutable semantics. Consider variables x and y of a type T, which has field or property m, and assume x is copied to y. If T has reference semantics, changes to x.m will be observed by y.m. If T has value semantics, one can change x.m without affecting y.m. If T has immutable semantics, neither x.m nor y.m will ever change. Immutable semantics can be simulated by either reference or value objects. Strings are immutable reference objects.
  • supercat
    supercat over 12 years
    Object references are passed by value (except when using the "ref" or "out" keyword). Think of objects as ID numbers. If a class variable holds "Object #1943" and one passes that variable by value to a routine, that routine can make changes to Object #1943, but it can't make the variable point to anything other than "Object #1943". If the variable was passed by reference, the routine could make the variable point hold "Object #5441".
  • Raymond
    Raymond over 12 years
    @supercat: If you agree (didn't see a +1) and want to explain to @ kenny, you need to @ him in. If you want to explain the difference between references and values to me, you've just done that... If you feel this answer is wrong and needs rewriting based on your comment, feel free to edit and/or add your own answer.
  • supercat
    supercat over 12 years
    @RubenBartelink: Thanks for the heads-up; I'd meant to notify Kenny. I wish the "object ID" description were used more widely; I think it makes things very clear. If a bodyshop worker is handed a piece of paper with a license number and asked to paint that car blue, he should be expected to find the car whose license matches the one on the paper and paint that, while leaving the number on the paper alone. He would not be expected to paint the paper blue, nor re-ink it with blue lettering.
  • Raymond
    Raymond over 12 years
    @supercat: I do like your explanation of ref vs val (and this followup anaology). I think kenny doesnt actually need any of this explained to him, (relatively) confusing as his comments were. I do wish we could all just remove these goddam comments though as they're just confusing everyone. The root cause of all this nonsense appears to be that kenny misread my answer and has yet to point out a single word that should be added/removed/replaced. None of the three of us have learned anything from the discussion we didnt already know and the other answer has a ludicrous number of upvotes.
  • Frank Visaggio
    Frank Visaggio almost 12 years
    entertaining yet educating, stackoverflow needs more posts like this
  • Conrad Frix
    Conrad Frix over 11 years
    While everything here is pretty much true it doesn't really explain the difference between by value by reference or out. At best it half explains the difference between reference and value/immutable types.
  • Shiva Kumar
    Shiva Kumar over 10 years
    From MSDN: A ref parameter must be initialized before use, while an out parameter does not have to be explicitly initialized before being passed and any previous value is ignored.
  • Sadiq
    Sadiq over 9 years
    You mean after all (in ref case) there's only one reference to data but two alias for it. Right?
  • supercat
    supercat about 9 years
    @DanielEarwicker: For functions Implemented in C#, the compiler will insist that out parameters must be written on all non-exceptional code paths; that is not enforced, however, for functions--including virtual function overrides--implemented in other languages. It is entirely possible, for example, that an implementation of IDictionary<TK,TV>.TryGetValue(TK, out TV) will leave its out parameter unmodified when a value is not found.
  • Nathan Tuggy
    Nathan Tuggy almost 9 years
    Well, this is a puzzling answer to see in LQP, to be sure; there's not a thing wrong with it except that it appears to be a long and thorough response to another comment (since the original question mentions Able and Baker in none of its revisions), as though this were a forum. I guess that wasn't really sorted out yet way back when.
  • Panzercrisis
    Panzercrisis about 8 years
    With out, can it be read at all within the method, before it's been set by that method, if it has been initialized before the method was called? I mean, can the called method read what the calling method passed to it as an argument?
  • Joyce Babu
    Joyce Babu over 7 years
    Upvoted for the clear explanation. But I think this doesn't answer the question, as it do not explain the difference between ref and out parameters.
  • Asif Mushtaq
    Asif Mushtaq over 7 years
    Amazing. can you explain same as for out keyword?
  • binki
    binki over 7 years
    @faulty You should really be checking out another question describing ref used with reference types ;-).
  • chviLadislav
    chviLadislav over 7 years
    There is a trick how to pass to a ref uninitialized object without any compile-time errors, see my answer
  • robert jebakumar2
    robert jebakumar2 about 7 years
    Panzercrisis, for "out", the called method can read if it is already set. but it must set it again.
  • displayName
    displayName almost 7 years
    Just in case somebody finds this answer only half-funny, please watch the movie "Office Space".
  • Patrick Artner
    Patrick Artner over 6 years
    and Dom and Peters boss would stand behin Dom (as out argument), forcing both to work on printing it out anew until Peter hands Domd the printout
  • Sebastian Hofmann
    Sebastian Hofmann over 6 years
    You can declare a variable inline: out double Half_nbr.
  • Bharathkumar V
    Bharathkumar V about 6 years
    Both ref and out cannot be used in method overloading simultaneously. However, ref and out are treated differently at run-time but they are treated same at compile time. CLR does not differentiate between the two in IL.
  • Ned
    Ned almost 6 years
    "In C#, a method can return only one value. If you like to return more than one value, you can use the out keyword." We can also use "ref" for returning value. So we can use both ref and out if we want to return multiple values from a method?
  • Iman Bahrampour
    Iman Bahrampour over 5 years
    In the c# 7 you can return multiple values with ValueTuples.
  • Daniel Botero Correa
    Daniel Botero Correa over 5 years
    If you want that code to write cat please pass that object along with the ' ref ' key like this: public static void Bar(ref MyClass someObject), Bar(ref myObject);
  • Kushan Randima
    Kushan Randima over 3 years
    An excellent explanation. This is very helpful for students who struggle to understand the core concepts of C#. Keep it up :-)
  • NetMage
    NetMage about 3 years
    @BharathkumarV Isn't your comment backward? ref and out are treated differently at compile time but are treated the same at run time.
  • starriet
    starriet about 2 years
    @thr just to clarify: ref/out are not like pointers in C/C++. Rather, just normal variables for objects are like pointers in C/C++. ref/out in C# is quite similar to the 'reference' in C++, which is absent in C.