What's the difference between the 'ref' and 'out' keywords?
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:
- The value is already set and
- The method can read and modify it.
The out
modifier means that:
- The Value isn't set and can't be read by the method until it is set.
- 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:
- The block of memory that holds data for someobject.
- 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
You should use out
in preference wherever it suffices for your requirements.
Comments
-
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 over 15 yearsAnother 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 over 15 yearsExactly. 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 over 15 yearsIn 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 over 15 yearsThis 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 over 15 yearsYes, you're right. I didn't think of immutable objects like strings because most object are mutable.
-
faulty over 15 yearsis 'ref' only applicable to value type? Since reference type is always pass by ref.
-
Rune Grimstad over 15 yearsYes. Value types including structs
-
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 about 14 yearsnot quite, as the accepted answer ref if directional and useless ignoring value-types if not passed back out.
-
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 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 about 14 yearsI 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 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 over 13 yearsThis answer most clearly and concisely explains the restrictions that the compiler imposes when using the out keyword as opposed to the ref keyword.
-
Keith over 13 yearsThis is wrong - try the following: add
someObject = null
toBar
end execute. Your code will run fine as onlyBar
's reference to the instance was nulled. Now changeBar
toBar(ref MyClass someObject)
and execute again - you'll get aNullReferenceException
becauseFoo
's reference to the instance has been nulled too. -
Deebster almost 13 yearsref Dom would have written the report in pencil so that Peter could modify it
-
Michael Blackburn almost 13 years@Deebster you know, that metaphor never did anything to you, why must you torture it so? ;)
-
Don Kirkby over 12 yearsWelcome 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 linea = "testing";
witha.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 over 12 yearsThere 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 over 12 yearsObject 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 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 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 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 almost 12 yearsentertaining yet educating, stackoverflow needs more posts like this
-
Conrad Frix over 11 yearsWhile 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 over 10 yearsFrom 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 over 9 yearsYou mean after all (in ref case) there's only one reference to data but two alias for it. Right?
-
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 ofIDictionary<TK,TV>.TryGetValue(TK, out TV)
will leave itsout
parameter unmodified when a value is not found. -
Nathan Tuggy almost 9 yearsWell, 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 about 8 yearsWith
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 over 7 yearsUpvoted for the clear explanation. But I think this doesn't answer the question, as it do not explain the difference between
ref
andout
parameters. -
Asif Mushtaq over 7 yearsAmazing. can you explain same as for
out
keyword? -
binki over 7 years@faulty You should really be checking out another question describing
ref
used with reference types ;-). -
chviLadislav over 7 yearsThere is a trick how to pass to a ref uninitialized object without any compile-time errors, see my answer
-
robert jebakumar2 about 7 yearsPanzercrisis, for "out", the called method can read if it is already set. but it must set it again.
-
displayName almost 7 yearsJust in case somebody finds this answer only half-funny, please watch the movie "Office Space".
-
Patrick Artner over 6 yearsand 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 over 6 yearsYou can declare a variable inline:
out double Half_nbr
. -
Bharathkumar V about 6 yearsBoth 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 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 over 5 yearsIn the c# 7 you can return multiple values with ValueTuples.
-
Daniel Botero Correa over 5 yearsIf 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 over 3 yearsAn excellent explanation. This is very helpful for students who struggle to understand the core concepts of C#. Keep it up :-)
-
NetMage about 3 years@BharathkumarV Isn't your comment backward?
ref
andout
are treated differently at compile time but are treated the same at run time. -
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.