Learn about the difference between value types and reference types in C#.
Have you enjoyed this video?
Subscribe now to the Productive C# YouTube channel and the newsletter to be the first to receive new videos and articles on C# and .NET and join a community of professional C# developers on Slack.
Transcript of the video
In this video I am going to explain the difference between value types and reference types in C#. This is a very important thing to understand when you are new to the C# language. The best way for learning this is by example.
Let's start with this console application. I have defined a value type called Point. In order to define a vlue type, I use the struct keyword in C#. This type contains an X and a Y that represent a point in space. It has a constructor and there is a Tostring method that basically returns a string representation of Point.
The main program instantiate point1 then assign point1 to point 2 and then attempt to change X and Y of point2 and finally is printing point1 and point2. Let's have a look at what happen in memory when you execute this code. As you can see we are printing (1,1) and (2,2). So this means that point1 and point2 are actually holding different locations of the data. When I do an assignment, what really happens is that a copy of the memory that point1 represents is copied into an another location that point2 represents. This means that point1 and point2 are actually two locations in memory that are completely indipendent from each others. If you attempt to change any information inside point2 nothing happen on point1. They are two completely isolated locations.
A value type holds the data withing his own memory allocation. When you do an assignment, a copy by value occurs and if you change that value nothing happen to the original value.
Let's see what happen when I change this struct to a class. The class keyword is how you define a refernece type in C#. The program code still compiles but the semantics is completely different. What happens at runtime is different.
Let's run this program and see what's happen. Now the result is (2,2) and (2,2). Interesting!
Reference types contains the memory address to an another memory location that holds the data. So point1 and point2 are just pointers to the same memory location. When you do point1 = point2 and those types are ference types, you are actually copying one pointer to an another. Then later on, when you actually change X and Y using point2 you are also changing indirectly what point1 points to because at the end of the day, point1 and point2 are pointing to the same exact location in memory.
So when you do an assignment between reference types, your are only assigning a reference to the location where the data is stored. So the two variables are dependent from each others and you need to keep this in mind when you work with C#. If you change point2.X and point2.Y you are also chaning point1.X and point1.Y.
This is the main differnece between value types and refernece types.
All the numberic data types in C# are value types. Booleans, characters, DateTimes are also value types. Anything that is defined as a struct is a value type in C#.
All value types implicitely inherit from System.ValueType.
Pay attention that some articles online say that value types are usually allocated on the stack. The usually part is very important. They are not alwyas allocated on the stack. Value types are allocated on the stack only when used directly inside methods. This is very efficient because garbage collection doesn't take place so performance is better. However, if you use a value type inside a class or inside an another reference type that it would be allocated on the heap. The memory they are using will be actually collected when the actual reference type will be collected. That's something to keep in mind. The location where the data is allocated (in the stack or the heap) doesn't really matter in terms of what a value type is. What really matters is the semantics. The fact that the value types holds the data withing its own memory allocation.
What are the reference types?
Strings, arrays, objects and delegates and anything that is a class in C# is a reference type and behaves with this semantic in mind. Reference types contains pointer to a memory location that holds the data. When you assign reference types you are only assigning a pointer to an another. You are not doing any copy by value.
The good thing about this is that it's extremely efficient to do an assignment between reference types. Insted if you do an assignment between value types it can be expensive especially if the value types takes a lot of bytes in order to be allocated.
It's a good practice to keep your structs less than 16 bytes.
It's a good practice to make sure your value types are immutable (so that it's not possible to change the memory that the value types holds after its being created). If you look closely at the .NET Framework, all the value types defined by the framework like DateTime, TimeSpan are immutable. If you call methods on those types, they will return new copies of those types.
If you are still confused about the two, I recommend you to play with struct and classes.
You can test if a particular type is a value type by using the is operator (is ValueType).
All reference types implement System.Object.
All value types implement ValueType that indirectly implements System.Object.
If you are considering to take the Microsoft C# specialist certification, this is a very important topic to master because you will be questioned on this. Good luck!
Looking to become a master C# 8 developer?