ElmsPlusPlus
ElmsPlusPlus

Reputation: 185

Use of C# 'ref' keyword compared to C++

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

Answers (3)

Michael Edenfield
Michael Edenfield

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

Jaime Torres
Jaime Torres

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

Konrad Rudolph
Konrad Rudolph

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

Related Questions