ref keyword in C#
Hello guys, I'm just reading a bit about the
ref
keyword. I understood that when we use that keyword, we tell the compiler that we want to directly work with the memory address of the variable and not a copy of it (when using it inside a method).
I have one question. I noticed that the ref
keyword is used both when writing the arguments during the method call like callMethod(ref variable)
and also during declaring the parameters of a method, we use the keyword, like static void changeValue(ref int x)
.
Can someone explain why ref should be used in both the arguments and parameters, why not use it either in argument or parameter22 Replies
my guess is for clarity, so you know that you are passing by reference
That is correct
yep I see
one last thing, consider the following code:
Normally, for objects, we store their reference, right? So any change made to an object directly affects the value at the memory address itself. So we don't really need to use the ref keyword with objects? But in the code above, why did we use it? What if we wouldn't use it?
Try printing
t.Something
after calling DoSomething
and see what happens 🙂
Both with and without ref
Okk, so from what I've understood:
Like every arguments passed without the ref keyword, we are always passing a copy of something. Similarly, here if we don't use the ref keyword, we would be passing a copy of the reference of t.
Now, when we pass a copy of the reference (no use of ref keyword), a local copy of x is created. Initially, both x and t have the same reference so any changes made to x should also affect t. But let's say we want to change the reference of x. We do so using the new keyword to assign a different memory location.
Now, since x is a copy of t, changing the reference of x won't change that of t. (I understood it but don't know it's still a bit unclear, I wanted to know how it would appear, like the memory structure, stack/heap etc).
So when we write x.Something without the ref keyword, the x.Something is only persistent within the method itself, but after that, it will be garbage collected (when needed) when the method ends?
Using the ref keyword allows the x.Something to persist though because both x and t have same reference
No
You were on the right track in the first half, but got a bit sidetracked
Translate this to C and pointers. A
class
local is a pointer to the heap
IE, if TestRef
is a class, t
has a type of TestRef*
Then, if you say ref TestRef x
, x
has a type of TestRef**
And it points the location of t
on the stack
So when you assign x = new TestRef()
, you're actually doing *x = new TestRef()
If you were to instead say TestRef x
, without the leading ref
, then the type of x
is just TestRef*
And x = new TestRef()
is just that; no pointer indirection occurs
So you just change your local, x
, which has no impact on t
yeah I see, like without the ref keyword,
x = new TestRef();
, there won't be able "indirect" pointer which will point to the reference where the reference of x is, like normally if we use the ref keyword, we would have 2 pointers, one pointing to where x is on the stack and the other pointing to where the reference of x is on the heap. Without the ref keyword, we only have the pointer which points to where reference of x is on the heap ?Yup
yep I see, here, where did I go wrong pls, when speaking about the reference ?
though because both x and t have same referenceThis is the bad fundamental They don't have the same reference
t
has the reference
x
is a reference to t
ah
I see
you means like t has the reference, say 0x100, x will also points to same reference of t, 0x100 ?
No, I mean that
x
will point to t
IE, TestRef** x = &t;
ahh I see
is it correct to say the following (assume that x has been passed by ref):
When we write
x = new TestRef()
, internally, the compiler noticed that we are allocating a new memory address to x, so what happens internally is that we are directly modifying the address at which t is, like we are doing *x = new reference
?Mostly. It's not really about the compiler noticing anything, that's just how assignment with
ref
variables works in C#
If you want to actually change the TestRef*
that x
points to, you'd have to use a different syntaxahh yeah I see true, because we can't really directly assign an object to something, we must use it's fields, like x.Something
yep I see
I believed I now have a clearer understanding of how the memory works internally, thanks ! Really appreciate, I even refresh some of my concepts in C 😂 💯
No problem. C is often the clearest way to explain how this works in detail, because it already made you think about it in the first place
yep, now I start to see why learning C is very important to understand memory stuff
sorry to disturb you once more, I have one lasttt question (it's on pointers in C though :c) consider the following:
Why when we pass the address of a pointer, (&t) we must use a double pointer as parameter to the function accepting that address? like TestRef**, why not use a single pointer?
You can overwrite it if it's a double pointer
Which you are doing in DoSomething
In C# what you wrote would be valid, because of GC, in C it's a memory leak
the object from main is never freed
You could still overwrite the object if it was a single pointer
But not its address
yeah I see, thanks !
like we can change the content of the object in the heap but the reference/address itself would be unchanged with a single pointer
yes