Getting CSharper #3: Understanding C# Types

In my previous post, we saw our first C# program, we covered how it was built and what kind of structures we should use and so on. In this post, we will talk about the types that we can use when we are building a program.

What is a Type ?

Type, in programming, can be defined as a data classification that determines the possible values for a data, the operations that can be performed and how it will be stored.

static void Main()
    string firstName = "Paulo";
    string lastName = "Ortins";
    int age = 23;
    int salary = 100;

    Console.WriteLine(firstName + lastName); // PauloOrtins
    Console.WriteLine(age + salary); // 123
    Console.WriteLine(firstName.ToUpper()); // PAULO

In the example above, we are declaring four variables, two of them are variable of type string, and the others are of type int. Note that, in both cases we are defining what we can store in each variable, and how we can manipulate them. When we sum two strings, we are doing a concatenation, on the other hand, when we sum two integers we are performing a math operation. We can capitalize every letter in a string with the ToUpper method, but this method doesn’t exist in type int.

Built-in Types

Built-in types are types that are specially supported by the compiler. They are also known as primitive types, we can group them to build other types. Below is a list of C# built-in types and how we can use each one.

Type Description Example
object The ultimate base type of all other types
object o = null;
string String type; a string is a sequence of Unicode characters
string s = "hello";
sbyte 8-bit signed integral type
sbyte val = 12;
short 16-bit signed integral type
short val = 12;
int 32-bit signed integral type
int val = 12;
long 64-bit signed integral type
long val1 = 12;
long val2 = 34L;
byte 8-bit unsigned integral type
byte val1 = 12;
ushort 16-bit unsigned integral type
ushort val1 = 12;
uint 32-bit unsigned integral type
uint val1 = 12;
uint val2 = 34U;
ulong 64-bit unsigned integral type
ulong val1 = 12;
ulong val2 = 34U;
ulong val3 = 56L;
ulong val4 = 78UL;
float Single-precision floating point type
float val = 1.23F;
double Double-precision floating point type
double val1 = 1.23;
double val2 = 4.56D;
bool Boolean type; a bool value is either true or false
bool val1 = true;
bool val2 = false;
char Character type; a char value is a Unicode character
char val = 'h';
decimal Precise decimal type with 28 significant digits
decimal val = 1.23M;

Custom Types

In C#, and in every language, we can combine primitive types to build our own types. For example, let’s create a type called Person, that has two attributes, a variable of int type called age and a variable of string type called name.

class Person
    string name;
    int age;
    public Person(string paramName, int paramAge)
        name = paramName;
        age = paramAge;

Initializing Data

string firstName = "Paulo";
int age = 23;
Person person = new Person("Paulo", 23);

Types are models for data. When we are creating data, we need to instantiate a type. Predefined types are specially supported by the compiler, so we can create data just assigning a value for them. In the other hand, for custom types, we have to use the new operator. The new operator trigger a constructor call, that is like a method used to build a instance for a given type. If you look carefully to our custom type Person, we can find a constructor with two parameters, that is called when a new Person is created.


Normally, we will have situations where we can store a value of one type in a variable of another type. It’s called a conversion. Conversions can be implicit or explicit. Implicit conversions are conversions where the compiler can guarantee that it will succeed and no information will lost in the conversion. Conversely, explicit conversions are conversions where the compiler cannot guarantee that it will succeed and information can be lost during conversion.

int x = 123; // 32-bit integer
long y = x; // Long are 64-bit so it can store a int 
int z = (int) y; // Long is bigger than int, so an explicit conversion is required

Value Types x Reference Types

Types in C# can be:

  • Value Types
  • Reference Types

Value types comprises almost all built-in types, like char, bool, int, short, long and so on.
Reference types comprises all custom types, classes, interfaces and arrays.

They’re are different by the way they are handled in memory. A variable of a value type stores a value, for example, a int variable stores a 32-bit data. Conversely, a variable of a reference type stores two values, a object value, and reference for that object. When we assign a value to a value type, we are modifying his value, but when we assign reference type, we are modifying a reference for an object. Let’s play with these differences.

Person person = new Person("Paulo",23); // Person is a reference type
int age = 23; // int is a value type

Console.WriteLine(; // Paulo
Console.WriteLine(age); // 23

int age2 = age;   // We are creating a new variable in memory with a value of 23
Person person2 = person; /* We are creating a new reference for a memory position,
                          * now both variable point for the same place 

age2 = age2 + 1;

// age and age2 are two different values

Console.WriteLine(age); // 23
Console.WriteLine(age2); // 24 = + "123";

// person and person2 are references for a same memory position

Console.WriteLine(; // Paulo123
Console.WriteLine(; // Paulo123

More Resources

One Comment

  1. Ping from Getting CSharper #4: Working with numbers Paulo Ortins | Paulo Ortins:

    […] our road through C#, that already covered a basic C# program and how types are used in C#, now we will work with numeric types that, together with string and arrays, are the most used types […]

Leave a Reply

Your email address will not be published. Required fields are marked *