Things you need to know as a C# developer - Build types

samfieldscc profile image Sam Fields Updated on ・3 min read

Alt Text

This post is part of a series of posts that I'm using to compile the most significant bits and tips about several things in C#. The purpose of this post is to be used as a way of review or quickly learn something new about C#.

In the first post of this series, we will summarize the C# build types, where every variable type is either a value type or a reference type.

Value Types

Variables that are value types contain their data, meaning value types are the value themselves. Below are some of the properties of this type:

  • Types like a struct, int, float are value types.
  • Each variable holds an independent instance or copy of the type.
  • Value changes to the variable do not affect other copies.
  • The value in the variable is the information.
  • Because it is not a reference, it cannot be null.
  • You might have to check the variable for null.

Passing Value Types by Value

Passing Value Types by Reference

In some cases, passing value types by value can create a performance bottleneck because the value passed (and copied) can be a complex data structure. Therefore, it can be a good idea to pass those data structures by reference. Bellow, a more straightforward example, shows how this works:

Reference Type

Variables of reference types store references to their data (objects), meaning that reference types reference something.

  • All C# classes are reference types.
  • The object instance shares its data, amongst other copies.
  • Value change affects all the references pointing to it.
  • The variable can point to nothing => it can be null.
  • Null checking may be required.

Passing Reference Types by Value

This example displays all the ways a reference can behave:

Passing Reference Types by Reference (using the ref keyword)

Reference types behave slightly differently when you use the ref keyword. The example below displays how the ref keyword can affect a variable when passed to a method:

Important Notes

  • The CLR can store objects in three locations: registers, stack, or the managed heap.
  • A value type does not exist exclusively in the stack! It can exist in any of those three locations.
  • A reference type can exist either on the managed heap or the stack. The location of the variable in memory depends on many factors. It's scope, the lifetime of the variable, and the implementation of the CLR.
  • Use the ref keyword to avoid copies of complex value type data structures.


1 What's the main difference between a value type and a reference type?

A value type holds the value itself, and a reference type holds a reference "memory address" to the value.

2 How do you pass a value type variable by reference to a method?

To pass a value type parameter by reference, we can use the "ref" keyword available since C# 7.0.

3 Value type variables are stored wherein the memory landscape?

Contrary to popular belief, value types can either be stored in the stack or the managed heap. In some cases, depending on the variable lifetime, it might even be stored in a register. It's difficult to pinpoint the precise location at any given point since the CLR implementation must also be taken into consideration.


[1]. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters

[2]. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-value-type-parameters

Posted on by:

samfieldscc profile

Sam Fields


I'm a Software Developer. Other than that, I'm either eating, sleeping, playing the violin or discovering the world. https://twitter.com/samfieldsccc


Editor guide


Thanks for sharing your knowledge.

Let me suggest an improvement.

Sample code provided for "Passing Value Types by Reference" is the same you wrote for "Passing Value Types by Value".

Best regards.


Hi Ivan,

Thanks for the response!

If you look more carefully at lines 3 and 15 you will see that in fact the parameters are being passed by reference with the use of the "ref" keyword. Which leads to different results. I invite you to try it on your machine or using dotnetfiddle.net/ to check this.

Best regards.