✅ out vs ref keyword usage
Hello guys, can someone explain when to use the out keyword and when to use the ref keyword please. I understand that in both scenarios, behind the scene, a pointer is passed so that any change made is reflected back. I also read that ref need to be initialized before passing value as argument while out doesn't but out need to be assigned a value inside the method itself.
I don't understand where one is used over the other though... can someone explain please, any use cases/best practices.
35 Replies
I am no expert, but one use case of the
out
usage is the try patter. Let's say you want to convert/parse from one type to another, without the out keyword the method would either throw an exception, or return null / default value, the later is extremely ugly implementation.
With the help of the out keyword it's possible to have the result in an out variable. Instead of thrown an exception, the variable would contain a null value. At the same time with try pattern the method could also return a boolean value.
You're right, they're pretty much the same under the hood. However:
* With
ref
, the caller needs to pass in a value, and the callee can read this. Because the caller is setting a value, the callee doesn't have to
* With out
, the caller does not have to pass in a value, but this means that the callee must assign one before returning
These have different use-cases: out
is for returning multiple values from a method, whereas ref
is less used, and is for allowing the callee to mutate a value owned by the caller.
For an example of why out
is useful, see the TryXXX pattern. It would be quite annoying to have to do:
Rather than just:
Another neat usage of
out
is to avoid defensive copy by calling it inside a readonly methodsThat needs a lot more background before it's meaningful 😛
(I suspect it will also just be confusing to OP, as they're learning about much more basic things)
it's a way to roundtrip inside readonly methods when avoiding defensive copies
see how they being used extensively here https://github.com/opentk/opentk/blob/master/src/OpenTK.Mathematics/Matrix/Matrix4.cs
that said, its common on large structs.
System.NumericsMatrixX also doing this trick
This goes way beyond the purpose of this thread tbh
how? 🙂 see the title again
Yeah, you need a background on what defensive copies are, what readonly methods are, what problems you can get, etc, before that even starts to make sense. Tbh I'm pretty clued up on that and I've no idea what you mean by "a way to roundtrip inside readonly methods" ><
Faker posts here really often and is very actively learning C#. I know that defensive copies and all that are definitely not what they are looking for on their skill level.
Good communication relies on being able to put yourself in your audience's shoes, and look at things with their level of knowledge, not yours
aight, fair
If they've just learnt what
ref
and out
are, defensive copies and readonly methods are waaay out of scopeto add to this
out
will also return a reference
anwered that so I won't be completely out of the loop of this post 😉i don't see async mentioned, so i'll mention that you can't use them with async
if it's a non-odd layout structs, just pass a span..
again we will be complained of being out os scope :kekw:
im not out of scope
this is about ref/out usage
yeah I see, like we don't need to initialize when used with out keyword?
yeah I see, this prevent the overhead of exceptions sometimes
defensive copy is the same thing as deep copy/shallow copy ?
no
Eh, it's similar in that it's a copy, but the compiler will copy a struct under-the-hood in some circumstances
the compiler will create a copy of the struct to prevent further possible mutation. I'd not say it's a deepcopy nor shallowcopy, just "defensive copy"
a lil bit abbout it can be read here https://devblogs.microsoft.com/premier-developer/the-in-modifier-and-the-readonly-structs-in-c/
yep I see
one last question, we say the
out
keyword is used to return "multiple" values; what do we mean by that? I'm a bit confused... in a method for example, we can only have a single return statementYou can have multiple parameters with an
out
keyword
You could also just use a method return value and use a Tuple or an object, but multiple out
parameters might be better suited for a methodas simple as this illustration right here
either way, we rarely do that nowadays because we have tuples now
also note, there's an obvious difference between the two. the
out
is actually returning a reference, whicle tuples dontBelow the example on the site is also some rules regarding
out
keywords, which FestivalDelGelato already hinted on.
The following limitations apply to using the out keyword:
- out parameters are not allowed in asynchronous methods.
- out parameters are not allowed in iterator methods.
- Properties cannot be passed as out parameters.yeah I see
The thing with async code and iterators is that it can't properly ensure that the
out
parameter is set or set to its latest value, so it's just not supported because of it.Specifically for last point there if your intention to use
out
as a ref return on properties, which out
can't, ref T Foo => ref someStruct
canSo generally with async code you just return an object or struct as the return type. Iterators' purpose is to return a collection of items so
out
parameters don't really make sense anywaynah, I believe the main reason would be related to concurrency that's why they dont allow it
If this is a comment on why async code can't have an out parameters then yes, most likely
All
out
parameters must be assigned a value before the method returns, but an async method effectively returns immediately by returning a Task, meaning the value wouldn't be available yet until the method reaches a point where the value would have been set.I now have an overview of the out keyword but still need to familiarise with it, thanks guys 👍
can you pls tag this as solved, this is pretty annoying ngl :awesome:

yep sorry