C# Data Types Tutorial For Beginners With Examples

In C# every variable and constant has a type. The types can be categorized as below:
  • Value types
  • Reference types
  • Pointer types

Before proceeding further lets briefly discuss about C# variables and constants.
Variables:
A variable represents a location in the system's memory. Using the variable a .NET program can access that specific memory location.
Constants:
A constant represents a fixed value which cannot be changed throughout the life of a program.

C# Value Types

A value type variable contains data directly. So, when a value type data is copied the actual data gets copied to a different location.
In .NET all value types derive directly from System.Valuetype class and System.Valuetype class derives from System.Object class. System.Object is the base type for all Types.
Below is the list of built-in value types:
Data TypeSymbolizesRange.NET Type
boolBoolean valueTrue or FalseSystem.Boolean
byteUnsigned 8-bit integer0 to 255System.Byte
charUnicode 16-bit characterU+0000 to U+ffffSystem.Char
decimal128-bit data type±1.0 x 10-28 to ±7.9 x 1028System.Decimal
double64-bit floating point value±5.0 x 10-324 to ±1.7 x 10308System.Double
float32-bit floating point value±1.5 × 10−45 to ±3.4 × 1038System.Single
intSigned 32-bit integer-2,147,483,648 to 2,147,483,647System.Int32
longSigned 64-bit integer–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807System.Int64
sbyteSigned 8-bit integer-128 to 127System.SByte
shortSigned 16-bit integer-32,768 to 32,767System.Int16
uintUnsigned 32-bit integer0 to 4,294,967,295System.UInt32
ulongSystem.UInt640 to 18,446,744,073,709,551,615Unsigned 64-bit integer
ushortSystem.UInt160 to 65,535Unsigned 16-bit integer
The above types are know as simple types and are available in .NET Framework's Common Type System (CTS).
The floating point types, decimal types and integral types are also called as numeric types. The numeric types are categorized in the below table:
Numeric TypeData Type
Floating point typefloat
double
Decimal typedecimal
Integral typesbyte
byte
char
short
ushort
int
uint
long
ulong
Apart from these built-in value types developers can create their own user-defined value types using the struct and enum keywords.
Visit Structs and Enums chapters to read about these data types in detail.
Structs:
A struct type is usually used for small groups of related variables. It is suitable for representing light weight objects such as Point, Rectangle, Color etc. struct keyword is used to declare a struct type.

In the below example we have created a new user-defined value type called as Square. Like int, bool etc. we can now declare a variable of type Square.

Example:
using System;
public struct Square 
{
    public int x, y;

    public Square(int p1, int p2) 
    {
        x = p1;
        y = p2;    
    }
}                    
Enums:
An enum type consists of a set of named constants called as the enumerator list.enum keyword is used to declare an enum type.

In the below example we have created a new user-defined value type called as Status. Like all other types we can declare variables of type Status.

Example:
using System;
enum Status {
    None, 
    Started, 
    In Progress, 
    Complete
};

C# Reference Types

A reference type variable contains address of the memory area where the actual data is stored. So, unlike value type variables, the reference type variable do not contain data directly but reference to the actual data.
Reference types are also called as objects. They derive directly from System.Object.
Below is the list of built-in reference types available in C#:
  • Object type
  • Dynamic type
  • String type
Object type
In .NET Framework the object type is an alias for System.Object class. As mentioned earlier System.Object is the base class of all the classes in .NET Framework. It is the ultimate starting point of the class hierarchy.
A variable of type object can be assigned any type of data. Which means integers, decimals, enums, strings etc can all be assigned to a object type variable.
Example:
class Program
{
    static void Main(string[] args)
    {
        object objRefType = "a";
        object objValType = 1;
            
        System.Console.WriteLine(objRefType.GetType());
        System.Console.WriteLine(objValType.GetType());

        System.Console.ReadLine();
    }
}
Output of the above program will be
System.String
System.Int32
Dynamic type
The dynamic type variables can store any type of data. The type checking for dynamic types are done only during run time.
In most cases dynamic types behaves like object types except that the type checking of object type is done at the compile time whereas the type checking of dynamic type is done at runtime.
Example:
class Program
{
    static void Main(string[] args)
    {
        dynamic dyn = 20;
        System.Console.WriteLine(dyn.GetType());     
    }
}
Output of the above program will be System.Int32
String type
In .NET Framework the string type is an alias for System.String class. A string type variable can be assigned any string data. A string data is always enclosed within double quotes.
Remember, unlike dynamic or object types you cannot assign any other types like int, float, struct etc. to string type. Doing so will result in an error.
Example:
class Program
{
    static void Main(string[] args)
    {
        string planetName = "Earth";
        System.Console.WriteLine(planetName.GetType());     
    }
}
Output of the above program will be System.String
Visit String types chapter to learn more about this type in detail.
Apart from these built-in reference types developers can create their own user-defined reference types using the class, interface and delegate keywords. We will cover these in subsequent chapters.

C# Pointer Types

Pointer type variable contains address of another variable. By default C# does not supports pointer types. However, using the unsafe keyword in C# we can create pointer types.
Pointer types do not inherit from object type and these types cannot be converted to object types or vice-versa.
Pointer type variables are created using the * symbol in front of the type. In the below example ipointer is a pointer type variable and holds address of integer variable actualValue.
Example:
class Program
{
    unsafe static void Main(string[] args)
    {
        int* ipointer;

        int actualValue = 10;

        ipointer = &actualValue;

        System.Console.WriteLine(*ipointer);            
        System.Console.ReadLine();
    }
}
Output of the above program will be 10