Reputation: 185
I have mainly worked in C++ and I am now using C# at my new job, and after doing some reading on here about the 'ref' keyword and c# value vs reference types I am still finding some confusion with them.
As far as I'm understanding these if you were passing these to a method these would be analogous C++ styles:
Value types:
public void CSharpFunc(value)
and
public void CPlusplusFunc(value)
Reference types:
public void CSharpFunc(reference)
and
public void CPlusPlusFunc(&reference)
'ref' / pointer
public void CSharpFunc(ref bar)
and
public void CPlusPlus(*bar)
Is this a correct analogy?
Upvotes: 10
Views: 1010
Reputation: 28338
It would be more accurate (though still not exactly the same) to swap your "Reference types" and "ref
" examples.
In C#, a reference type is a type that is always accessed internally via a reference to an instance of the type. It is easiest to thing of these as "pointers" in the C++ sense: you allocate memory, run the constructor(s), and get back a value that indirectly refers to the object you want. The difference between C# and C++ here is that in C#, this is a property of the type, not of the variable. A type is either always a reference type or always a value type. One effect of this is that you don't have to do anything special to use a reference type (there is no "dereference" operator in managed C# code); the compiler assumes that reference type variable access is indirected. In C++ you would still need to use the ->
operator, because you can have both value and reference variables of the same type (object x
vs. object *x
).
The ref
keyword is used to pass parameters by reference; those parameters can be either a value type (like int
) or a reference type. While the implementation of the ref
keyword is ultimately an address-of/pointer-to type operation (exactly as &
is in C++), ref
(and out
) produce a special type of object called a managed reference, which is different from a reference type in that you can have managed references to value types. This is almost exactly the way C++ works: an int&
is a special type of "reference to an int" that is distinct from int *
, even though both are basically using pointer indirection to access a variable. Similarly, in C# you can have a ref Object
, which would be effectively an object *&
.
Upvotes: 3
Reputation: 10515
Yes, you are mostly correct, (s/*/*& and you're 100% there). As @weston mentioned, out
is an additional keyword to be familiar with. The only cute thing you can do with ref
is overload a function that's not ref.
class Person {
string Name { get; set; }
string Address { get; set; }
int age { get; set; }
}
public void UpdateName(Person p)
{
if (p == null)
{
return;
}
p.Name = "Tom";
}
public void UpdateName(ref Person p)
{
if (p == null)
{
p = new Person();
}
p.Name = "Tom";
}
Obviously useless, but it does provide for some interesting opportunities (and bad design). out
does not provide the same overload functionality.
If you would like 1 for 1, you can always block your code with unsafe
.
Upvotes: 1
Reputation: 545985
Is this a correct analogy?
Despite what the other answers say, no. What ref
means in terms of C++ actually depends on the type. For value types, your assessment is correct (or close enough). For reference types, a more suitable analogy would be a reference-to-pointer:
public void CPlusPlus(type*& bar)
The whole point about ref
is that you can change the reference being passed in. And you can’t do that in C++ by simply passing a pointer:
void f(type* bar) {
bar = new_address;
}
type* x;
f(x);
This code won’t change the caller’s value of x
. If you had passed bar
as type*&
, on the other hand, it would have changed the value. That is what ref
does.
Furthermore, a reference in C# is quite unlike a reference in C++, and much more like a pointer in C++ (in that you can change which object the reference refers to).
Upvotes: 12