Walk Through C# Types
2020-06-06
Slide in HTML version: https://bit.ly/2Ui4dC2
Agenda
-
C# Types Overview
-
Value Type and Reference Type
-
Nullable Type
-
Structure type and Enumeration type (
struct
andenum
) -
Common Questions & Answers
-
Wrap up
Overview: A diagram of C# Types
This tutorial will cover most of the terms in the diagram, but we are not going to dive deep into dynamic type.
Value types
- most built-in types (all numeric types, the char type, the bool type)
- custom struct types
- custom enum types
Reference types
- string type
- object type (all class, array, delegate, interface types)
- dynamic type
2. Value Type and Reference Type
Example of different types
// ** Value Type **
// built-in types
Int32 number = 1;
int i = 0;
// struct
struct Point { public int X; public int Y; }
// enum
enum Color { Red, Green, Blue };
// ** Reference Type **
// string type
string s = "abc";
string[] stringArray = ["a", "b", "c"];
List<string> stringList = new List<string>();
// object type
Student student = new Student();
List<Student> studentList = new List<Student>(); // Object List
// dynamic type
dynamic dynamicVariable = 1;
Simple Types (Built-in value types)
What is the fundamental difference between value type and reference type?
The fundamental difference is how they are handled in memory.
Stack and Heap (both are in the RAM)
Stack is used for static memory allocation, it happens at compile time.
Heap is used for dynamic memory allocation, it happens at runtime.
What is compile time and runtime?
Compile time is when you build your project.
Runtime is when you execute your project.
Compare Value Type and Reference Type (1)
Difference 1: stores on different memory location
-
Value types are stored directly on the stack during compile time.
-
Reference types have an object reference variable created on the stack during compile time. At runtime, the actual custom object of the Reference type will be created on the Heap.
Note: This also means the reference types have some overhead in terms of memory consumption, each reference to an object requires an extra four or eight bytes, depending on whether the .NET runtime is running on a 32- or 64-bit platform.
Compare Value Type and Reference Type (2)
Difference 2: how they get destroyed
-
Value types are destroyed immediately after the scope is lost.
-
For Reference types, only the reference variable on the stack is destroyed after the scope is lost. The actual object on the heap is later destroyed by garbage collector.
Compare Value Type and Reference Type (3)
Difference 3: how they are copied
-
When you copy a value type , a new copy of that variable gets created and modifications on the original variable will not affect the values contained by the copied variable.
-
When you copy a reference type, we only get a copy of the reference variable. Both the reference variables points to the same object on the heap. So, operations on one variable will affect the values contained by the other reference variable.
// Value Type
int i = 0;
int j = i;
j = 1;
Console.WriteLine($"i = {i}, j = {j}");
// Reference Type
Student s1 = new Student(1, "Luna");
Student s2 = s1;
s2.id = 2;
Console.WriteLine($"Student 1 id = {s1.id}, Student 2 id = {s2.id}");
Compare Value Type and Reference Type (4)
Difference 4: null
Reference type can be assigned to null, which means the reference points to no object, and trying to access the fields of a null object will cause run-time error (NullReferenceException).
Value types cannot have a null value, it will cause compile-time error.
Nuallable Reference type and nullable value types will be discussed in the next section.
// Reference type can be null
Point p = null;
Console.WriteLine (p.X); // Run-time error
// value types cannot have null value
int x = null; // Compile-time error
Q: Is Array of Value type a Reference type or a Value type?
Arrays (even of value types like int) are reference types in C#.
In C#, arrays are actually objects. System. Array
is the abstract base type of all array types.
// I am also a reference type!
int[] intArray = new int[]{1, 2, 3};
3. Nullable Type
Nullable Type
The nullable value types are available beginning with C# 2.
C# 8.0 has introduced nullable reference types, C# also has a construct called nullable value types for representing value-type nulls.
// ** nullable syntax (?) **
public int Id? {get; set;}
public List<Books> nullableList? {get; set;}
// ** null-forgiving operator (!) **
public int Id! {get; set;}
public List<Books> nonNullableList! {get; set;}
What is this used for?
-
Avoid null reference mistakes at compile-time.
-
A way to explicitly express our intent.
-
Nullable Reference Type is by default enabled in .NET Core 3.0 projects.
4. Structure type and Enumeration type
struct and enum - data structures
Structure is a group of basic data type variables, it is similar to class (a data type in OOP).
Enumeration is a data structure that assigns integer values to string type data values.
struct and enum types are value types stored on the stack, if used properly, they can be more efficient than class.
enums
enums are basically a set of named constants. They are declared in C# using the enum
keyword. Every enum
type automatically derives from System.Enum
.
// enum declaration (no need to use new keyword)
enum Rating {Poor, Average, Okay, Good, Excellent}
// assign enum value
Rating r1 = Rating.Excellent;
// GetNames method can get the names of the constants in the enum
foreach(string s in Rating.GetNames(typeof(Rating)))
Console.WriteLine(s);
// GetValues method can get the values of the constants in the enum
foreach (int i in Rating.GetValues(typeof(Rating)))
Console.WriteLine($"Rating Value = {i}");
// enum usage
Rating IncrementRating(Rating r)
{
if(r == Rating.Excellent)
return r;
else
return r+1; // can use arithmetic operator on enum
}
structs
struct is a weakened version of class.
Example of structs in the .NET Framework:
- int (System.Int32),
- double(System.Double) etc.
public struct CustomerStruct
{
public string name { get; set; }
public int ID { get; set; }
public CustomerStruct(int Id, string Name)
{
// struct cannot have parameterless constructor
ID = Id;
name = Name;
}
}
Difference between struct and class
-
- Structs cannot have destructors, Class can have destructors.
- Because structs are value type and recall that value type will be destroyed when lost its scope.
-
Parameterless Constructor
- Structs cannot have explicit parameterless constructor whereas a class can.
- You can still call the default constructor without parameter (automatically implemented), it simply initializes all values to their zero-equivalents.
-
- Struct cannot inherit from another class whereas a class can.
- Both structs and classes can inherit from an interface.
- No one can inherit from struct because it is a sealed type thus it loses the ability of inheritance.
When to use structs over classes?
-
If instances of the type are small and commonly short-lived or are commonly embedded in other objects.
-
Define a struct when the type has all of the following characteristics:
- It logically represents a single value, similar to primitive types (
int
,double
, etc.). - It has an instance size under 16 bytes.
- It is immutable (cannot be changed).
- It will not have to be boxed frequently.
- It logically represents a single value, similar to primitive types (
Boxing and Unboxing
Wrap up
-
C# Types (Value Type and Reference Type)
-
Stack and Heap
-
Nullable Type
-
Struct and Enum in Value Type
-
Difference between struct and class
- boxing and unboxing
Thanks for listening / reading :)