1- Types Basics

In this article

  1. Variables
  2. Data Types
    1. Characteristics
    2. Members of a Type
  3. Syntax
  4. Predefined Types
    1. Instantiation
    2. Taxonomy
      1. Value types
      2. Reference Types
  5. Custom Types
    1. Instantiation
    2. Instance vs Static Members
      1. Instance Members
      2. Static Members
  6. Type Conversion
    1. Conversion Types
      1. Implicit Conversion
      2. Explicit Conversion
      3. Additional Notes
  7. Value Types Versus Reference Types
    1. Value types
      1. Storage Overhead
    2. Reference types
      1. Storage Overhead
    3. Null


A variable denotes a storage location that can contain different values over time.

Data Types

  • A type defines the blueprint for a value.
  • Datatypes are sets (ranges) of values that have similar characteristics. For instance, byte type specifies the set of integers in the range of [0…255].


Data types are characterized by :

  • Name – for example, int;
  • Size (how much memory they use) – for example, 4 bytes;
  • Default value – for example 0.

Members of a Type

A type contains :

  • Data members. (fields)
  • Function members. (methods)


<type> <identifier> = value literal | new <custom_type>(...);


int age = 4;
Person Owner = new Person("Mohamed");
WeekDays today = WeekDays.Saturday; // for enumerations

Predefined Types

Predefined types are types that are specially supported by the compiler. for example, Primitive types.


Predefined types can be instantiated by using a literal. for example, 12 or "Hello Wordl!".

int age = 26;
string name = "Mohamed Halawa"


The predefined types in C# are as follows:

Value types

  • Numeric
    • Signed integer (sbyte, short, int, long)
    • Unsigned integer (byte, ushort, uint, ulong)
    • Real number (float, double, decimal)
  • Logical (bool)
  • Character (char)

Reference Types

  • String (string)
  • Object (object)

Predefined types in C# alias .NET types in the System namespace. There is only a syntactic difference between these two statements:

int i = 5;
System.Int32 i = 5;

The set of predefined value types excluding decimal are known as primitive types in the CLR.

Primitive types are so called because they are supported directly via instructions in compiled code, and this usually translates to direct support on the underlying processor; for example:

Custom Types

A user can define his own data type to accommodate his needs. for example, creating a class type to model a person:

class Person
    string _name;

    public Person(string name){
        this._name = name;

Person Owner = new Person("Mohamed Halawa");


Custom types defined by class, struct keywords can be instantiated using the new Operator.

The new Operator creates instances of a custom type.

  • Immediately after the new operator instantiates an Object, the object’s constructor is called to perform initialization.
  • A Constructor is defined like a method, except the method name and return type are reduced to the name of the enclosing type.
public Person( string name ){ this._name = name; }

Instance vs Static Members

Instance Members

  • The data members and function members that operate on the instance of the type are called instance members.

Static Members

  • Data members and function members that don’t operate on the instance of the type can be marked as static.
  • To refer to a static member from outside its type, you specify its type name rather than an instance.

Type Conversion

C# can convert between instances of compatible types. A conversion always creates a new value from an existing one.

Conversion Types

  • Implicit conversion
  • Explicit conversion

If the compiler can determine that a conversion will always fail, both kinds of conversion are prohibited.

Implicit Conversion

Implicit conversions are allowed when both of the following are true :

  • The compiler can guarantee that it will always succeed.
  • No Information is lost in the conversion.

Implicit conversion always happen automatically.

Because long type has a bigger storage capacity (64-bit) than int type (32-bit), the conversion from int to long happens Implicitly.

int x = 12345;
long y =x ;

Explicit Conversion

Explicit conversions are required when one of the following is true:

  • The compiler cannot guarantee that it will always succeed.
  • Information might be lost during conversion.

Explicit conversions require a cast.

Because short the type has a smaller storage capacity (16-bits) than int type (32-bit), the conversion from int to long happens explicitly and requires a cast.

int x = 12345;
short y =(short)x ;

Additional Notes

  • The numeric conversions are built into the language.
  • The compiler doesn’t enforce the aforementioned rules with custom conversions, so it’s possible for badly designed types to behave otherwise.
  • Conversions that involve generics can also fail in certain conditions.

A minor caveat is that very large long values lose some precision when converted to double.

Value Types Versus Reference Types

All C# types fall into the following categories:

  • Value types
  • Reference types
  • Generic type parameters
  • Pointer types

The fundamental difference between value types and reference types is how they are handled in memory.

Value types

Value types comprise most built-in types specifically :

  • Numeric types
  • Char type
  • Bool type
  • Custom struct
  • Enum types
  • The content of a value-type variable or constant is simply a value. For example, the content of the built-in value type, int, is 32-bit of data.
  • You can define custom value type with the struct keyword
public struct Point {int X,Y;}

The assignment of a value-type instance always copies the instance; for example:

Point p1 = new Point();
p1.X= 7;

Point p2 = p1;   // Assignment causes copy
Console.WriteLine(p1.X); // 7
Console.WriteLine(p2.X); // 7

p1.X = 9; // Changing the original value won't affect the copied one.
Console.WriteLine(p1.X); // 9
Console.WriteLine(p2.X); // 7

Storage Overhead

Value-type instances occupy precisely the memory required to store their fields, for example:

// Any instance of the struct will occupy 8 bytes of memory
struct Point{
    int x; // 4bytes
    int y; // 4bytes

Technically, the CLR positions fields within the type at an address that’s a multiple of the fields’ size (up to a maximum of 8 bytes).

For example, the following will consume 16 bytes of memory with the 7 bytes following the first field wasted.

// Total 9 bytes
// CLR will position the fields into 16bytes (multiple of 8)
// the remaining 7 bytes (16 - 9) will be wasted !
struct A{
    byte b; // 1 byte
    long l; // 8 byte

You can override this behaviour by applying the StructLayout attribute.

Reference types

Reference types comprise all :

  • Array
  • String
  • Class
  • Delegate
  • Interface types

Assigning a reference-type variable copies the reference, not the object instance. This allows multiple variables to refer to the same object—something not ordinarily possible with value types.

If we repeat the previous example, but with Point now a class, an operation to p1 affects p2:

Point p1 = new Point();
p1.X = 7;
Point p2 = p1; // Copies p1 reference
Console.WriteLine (p1.X); // 7
Console.WriteLine (p2.X); // 7
p1.X = 9; // Change p1.X
Console.WriteLine (p1.X); // 9
Console.WriteLine (p2.X); // 9

Storage Overhead

  • Reference types require separate allocations of memory for the reference and object.
  • The object consumes as many bytes as its fields, plus additional administrative overhead.
  • The precise overhead is intrinsically private to the implementation of the .NET runtime, but at minimum, the overhead is 8 bytes, used to store a key to the object’s type as well as temporary information such as its lock state for multithreading and a flag to indicate whether it has been fixed from movement by the garbage collector.
  • Each reference to an object requires an extra 4 or 8 bytes, depending on whether the .NET runtime is running on a 32-bit or 64-bit platform.


A reference can be assigned the literal null, indicating that the reference points to no object.

Point p = null;
Console.Writeline(p == null); // True

// The following line generates a runtime error
// (a NullReferenceException is thrown):

class Point{...}

In contrast, a value type cannot ordinarily have a null value:

Point p = null; // Compile-time error
int x = null;   // Compile-time error

struct point {...}

C# also has a construct called nullable value types for representing value-type nulls.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s