Data Types in C# Programming

Data type is a categorization of variable to define what type of data can be stored in that variable. In C#, declaration of a data type is compulsory. This helps compiler know what type of data will be stored in that variable.

These data types can be categorized in following three types:

  1. Value Type
  2. Reference Type
  3. Pointer Type

Value Type

These data types are used to store data. They can store numbers or alphabets. Their examples are int, float, long, char etc. Each of these data types have different memory size, range, default value etc. Some of these value types are listed below:

bool

bool is a data type that can store either true or false. Many expressions like if use this boolean value for evaluation. It takes 1-byte size and its default value is false. For example:

            bool condition = true;
            if (condition)
                Console.WriteLine("Condition is true");
            else
                Console.WriteLine("Condition is false");

Output

Condition is true

byte

byte is a data type that can store value from 0 to 255. It is an unsigned integer and takes 8-bit memory. Example of byte declaration and initialization is given below:

byte firstByte; //Declaration
firstByte = 0; //Initialization

byte secondByte = 255; //Declaration and initialization in same line

char

char is a data type that can store unicode character ranging from U +0000 to U +FFFF. It takes 16- bit of memory space. We can assign a single letter, number or symbol. We can also assign integer value but it must be casted as a char. Example for char declaration is given below:

char firstChar; //Declaration
firstChar = 'c'; //Initialization

char secondChar = 'd'; //Declaration and initialization in same line

char thirdChar = (char)100; //Assigning number cast

decimal

decimal is a data type that can store decimal values ranging from (-7.9 x 1028 to 7.9 x 1028) / (100 to 28). It takes 128-bit of memory. We must use 'm' or 'M' as a suffix for a number to be treated as decimal, not doing so will cause an error. Example for decimal declaration is given below:

 decimal d = 1.1m;

Decimals have many other in-built features like MaxValue, MinValue, One, Zero, MinusOne, Ceiling, Floor, Add, Multiply, Subtract, Divide, Remainder, Truncate, Negate, Round, MidpointRounding. Use of these features are shown below:

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine(decimal.MaxValue); //Maximum value of decimal type
        Console.WriteLine(decimal.MinValue); //Minimum value of decimal type
        Console.WriteLine(decimal.One); //Shows 1
        Console.WriteLine(decimal.Zero); //Shows 0
        Console.WriteLine(decimal.MinusOne); //Show -1
        Console.WriteLine(decimal.Ceiling(1.9M)); //Rounds off to larger integer
        Console.WriteLine(decimal.Floor(2.1M)); //Rounds off to smaller integer
        Console.WriteLine(decimal.Add(1.9M, 2.1M)); //Adds two numbers
        Console.WriteLine(decimal.Multiply(2.0M, 3.0M)); //Multiplies two numbers
        Console.WriteLine(decimal.Subtract(2.1M, 1.9M)); //Subtracts two numbers
        Console.WriteLine(decimal.Divide(6.2M, 3.1M)); //Divides two numbers
        Console.WriteLine(decimal.Remainder(4.3M, 2.0M)); //Displays remainder when 4.3M is divided by 2.0M
        Console.WriteLine(decimal.Truncate(1.9M)); //Removes every decimal after decimal point
        Console.WriteLine(decimal.Negate(2.1M)); //Negates the number
        Console.WriteLine(decimal.Round(2.119M, 2)); //Rounds off to two digits after decimal point
        Console.WriteLine(decimal.Round(7.5M, 0, MidpointRounding.ToEven)); //If there is 5 after decimal point rounds off to near even number
        Console.WriteLine(decimal.Round(4.5M, 0, MidpointRounding.AwayFromZero)); //If there is 5 after decimal point rounds off away from zero
        Console.ReadLine();
    }
}

Output

79228162514264337593543950335
-79228162514264337593543950335
1
0
-1
2
2
4.0
6.00
0.2
2
0.3
1
-2.1
2.12
8
5

double

double is a data type that can store data ranging from ±5.0 × 10−324 to ±1.7 × 10308 and is a double-precision floating point. It takes 64-bit memory space. To assign value as double we must use 'd' or 'D' as suffix. Example for declaration and initialization of double data type is given below:

double firstDouble = 2.2d; //Declaration and initialization in single line

float

float is a data type that can store single-precision floating point ranging from -3.4 × 1038 to +3.4 × 1038. It takes 32-bit of memory space. To assign value as float type we must use 'f' or 'F' as suffix. Example of declaration and initialization of float data type is given below:

float firstFloat = 3.4f; //Declaration and initialization in single line

int

int is a data type that can store signed integer ranging from -2,147,483,648 to 2,147,483,647. It takes 32-bit of memory space. Example for declaration and initialization of int data type is given below:

int myInt = 2; //Declaration and initialization in single line

long

long is a data type that can store signed integer ranging from -923,372,036,854,775,808 to 9,223,372,036,854,775,807. It takes 64-bit of memory space. Suffix 'l' or 'L' can be used when initializing. Example for declaration and initialization of long data type is given below:

long myLong1 = 212445564; //Without suffix L and Declaration and initialization in single line
long myLong2 = 212445564L; //With suffix L and Declaration and initialization in single line

sbyte


sbyte is a data type that can store signed integer ranging from -128 to 127. It takes 8-bit of memory space. Example for declaration and initialization of sbyte data type is given below:

sbyte mySbyte = 127; //Declaration and initialization in single line

short

short is a data type that can store signed integer ranging from -32,768 to 32,767. It takes 16-bit of memory space. Example for declaration and initialization of short data type is given below:

short myShort = 32767; //Declaration and initialization in single line

uint

uint is a data type that can store unsigned integer ranging from 0 to 4,294,967,295. It takes 32-bit of memory space. Suffix 'u' or 'U' can be used when initializing.  Example for declaration and initialization of uint data type is given below:

uint myUint1 = 489456u; //With suffix u And Declaration and initialization in single line
uint myUint2 = 489456; //Without suffix u

ulong

ulong is a data type that can store unsigned integer ranging from 0 to 18,446,744,073,709,551,615 . It takes 64-bit of memory space. Example for declaration and initialization of ulong data type is given below:

ulong myUlong = 24862489456; //Declaration and initialization in single line

ushort

ushort is a data type that can store unsigned integer ranging from 0 to 65,535. It takes 16-bit of memory space. Example for declaration and initialization of ushort data type is given below:

ushort myUshort = 65535; //Declaration and initialization in single line
Summary of Value Types in C#
Data Type Range Represents Size Default Value
bool True or false Boolean Value 1-byte False
byte 0 to 255 unsigned integer 8-bit 0
char U +0000 to U +ffff unicode character 16-bit '\0' 
decimal (-7.9 x 1028 to 7.9 x 1028) / (100 to 28) decimal values 128-bit  0.0M 
double ±5.0 × 10−324 to ±1.7 × 10308 double-precision floating point 64-bit 0.0D
float -3.4 × 1038 to +3.4 × 1038 single-precision floating point 32-bit 0.0F 
int -2,147,483,648 to 2,147,483,647 signed integer 32-bit 0
long -923,372,036,854,775,808 to 9,223,372,036,854,775,807 signed integer 64-bit 0L
sbyte -128 to 127 signed integer 8-bit 0
short -32,768 to 32,767 signed integer 16-bit 0
uint 0 to 4,294,967,295 unsigned integer 32-bit 0
ulong 0 to 18,446,744,073,709,551,615  unsigned integer 64-bit 0
ushort 0 to 65,535 unsigned integer 16-bit 0

Reference Type

Unlike Value Type, Reference Type doesn't store data but it stores memory address that holds the data. For example: Object, Dynamic, String etc.

Object Type is an alias for System.Object class. It can accept value of any data type. When a value type is converted to object type it is called boxing and when object type is converted to value type it is called unboxing. Example to understand object type:

using System;

class Program
{
    static void Main()
    {
        object myInt, myFloat, myChar;
        myInt = 10; //This is called boxing. Object as integer
        myFloat = 1.5; //Object as floating point
        myChar = 's'; //Object as character
        Console.WriteLine(myInt);
        Console.WriteLine(myFloat);
        Console.WriteLine(myChar);
        Console.ReadLine();
    }
}

Output

10
1.5
s

Dynamic Type is very similar to Object Type. The only difference is that type checking will be done at run time. Declaration and initialization of Dynamic Type is:

dynamic a = 1; //Declaration and initialization in single line

String Type allows you to store any number of unicode characters. Assignment in String Type can be done in two ways, quoted and @quoted. For Example:

String name = "This is string"; //quoted
@"This is string"; //@quoted

We can also compare and concatenate strings. We can compare two strings using '==' or '!=' operators and concatenate two strings using '+' symbol. For Example:

using System;

class Program
{
    static void Main()
    {
        string a = "This is ";
        string b = "string";
        a = a + b; //Concatenation
        Console.WriteLine(a);
        if (a == b) //Comparison
            Console.WriteLine("They are same");
        else
            Console.WriteLine("They are not same");
        Console.ReadLine();
    }
}

Output

This is string
They are not same

There are some User Defined reference type as well. They are class, interface and delegate.

Pointer Type

Pointer Type stores address of other data type, but, we cannot use it on Reference Types. This type might look similar to Reference Type but it cannot be tracked by the default garbage collection mechanism. We can create pointer type by using "*" after type. For Example:

int* var;

Here, var is a pointer variable.