C# Types [Value, Reference] Explained

Gilad Bar Ilan
Nerd For Tech
Published in
5 min readMar 12, 2021

--

In C# we can find three different kinds of types, Value, Reference, Pointer types. In this article, we are going to focus on Reference & Value types.

So What are Reference & Value types?

The Main Difference

The main difference between value & reference types is by their assignment.

int a = 5;
int b = a;
b++;

In the example above, we assign to the variable “b” the value of the variable “a”, and after that, we increase the value of b.

What is the value of b and what would be the value of a?
Well, as you probably knew that the value of b is now 6 and the value of a is still 5.

The reason for that is because on the assignment we copied the value from a to b in a call by value assignment.

However, is it always like that? let’s look at the following example:

SampleClass instance = new SampleClass();
instance.age = 45;
SampleClass second = instance;
second.age = 60;
Console.WriteLine(second.age);
Console.WriteLine(instance.age);

In the example above, both of the outputs would be 60, the reason this is because classes are Reference Types, which means that after we assigned that they point to the same place on the memory, and when we change second, the instance would be changed as well.

Why do we have that?

After we saw the reference and value types comes a question. Why would I want to have the reference type? Why would I create an instance that works on the sample place in the memory as my other instance?

Let’s assume we have a function that gets an array of strings in an unknown size. (arrays are also a Reference Type).

In that case, think about the time it will take for the computer to copy all the elements of the array if the array has 100,000 values.

public static void Main(string[] args)
{
int[] arr = new int[100000];
CallMyFunc(arr);
}
public static void CallMyFunc(int[] a)
{
Console.WriteLine("Pow!");
}

In the example above, if arrays would have been a value type it would have taken a lot of time to copy all values to the “a” parameter.

That’s why we have both Value and Reference types, when it comes to small sizes to copy like an integer it won’t take a lot of time to copy the integer value because its only 4 bytes.

However, in the example above it would have to copy (In case arrays were value type) 100000 * 4 = 400,000 bytes to a new parameter.

How to make Value Type with a call by reference

Let’s assume that you have a function called “Pow” and you want your function to get an integer in a call by reference way.

Well, C# offers two ways to do that, ref & out.

public static void Main(string[] args)
{
int a = 5;
Pow(ref a); //now a value is 6
Console.WriteLine(a); //prints 6
}
public static void AddToA(ref int b)
{
b++;
}

In the example above, we used ref and by that, we referred to the calling function as well, which means we got the address and by doing that we could change both the parameter and both the calling value.

public static void Main(string[] args)
{
Pow(out int b);
Console.WriteLine(b); //prints 5
}
public static void AddToB(out int c)
{
c = 5;
}

The out keyword forces initializing in the function, which means that after the function ends we can be sure that b stores a value. Because it forces initializing inside the function, we can declare the variable inside the calling in the main program as you can see above.

If we wouldn’t have the line of “c = 5” an error would be thrown because we cannot create a function that uses the out keyword and doesn’t initialize the value it gets.

public static void Main(string[] args)
{
int b = 7;
Pow(out b);
Console.WriteLine(b); //prints 5
}
public static void AddToB(out int c)
{
c = 5;
}

We can also use an already declared variable with the out keyword. Using those keywords we can refer to the caller and change his value too, we can also “return” multiple values in the same function.

ReferenceEquals Function

If you want to check whether two types point to the same address. You can use the ReferecneEquals function

SampleClass a = new SampleClass();
SampleClass b = a;
Console.WriteLine(ReferenceEquals(a, b)); //true
Console.WriteLine(ReferenceEquals(a, new SampleClass())); //false

Why is string a Reference Type?

Well, we all know that string works like a value type. When we assign a variable to another variable and then we change one of them doesn’t cause the other to change too.

Like it the example:

string a = "Nice Article!";
string b = a;
b += " By Gilad Bar Ilan"; //a still holds "Nice Article!"

However, if we would write ReferenceEquals before the change we’ll get True

string a = "Nice Article!";
string b = a;
Console.WriteLine(ReferenceEquals(a,b)); //prints true

The reason for this is because every time we chain to a string a new value, the string creates a new instance in the memory, and after we do that he is not related to the previous string anymore.

Because strings are immutable, we see the strings act like value types.

If the strings were mutable

string a = "hello world";
string b = a;
a[0] = 'b';

then the code above would have to change the “b” variable as well.

So, Why Strings Are Reference Types?

After this whole discussion comes a question, why string is a Reference Type?

Well, this is related to what we've talked about before. Let’s assume that strings were Value Types, in that case, if we have a string that his length is 100,000 chars.

It would make our program act very slowly, by making it a Reference Type we can make our program run faster.

The only concession we had to take by making strings as Reference Types instead of Value Types was that strings are immutable.

Struct & Class

Structs and classes are great examples of Value and Reference Types.

Structs are value types and classes are reference types.

When we talk about small pieces of data like the KeyValuePair structure, we would rather use struct because it’s not that slow to copy that kind of struct.

Whenever we talk about big pieces of data that can take a while to copy we would rather use a class and by that make the copy by reference.

Congratulations now you know the differences between Reference & Value type!

--

--