Beginner 20 min readModule: Module 2: Type System, Value vs Reference, Records & Nullable Types
Type System, Nullable References & Records
Master C# type fundamentals: Value Types (structs) vs Reference Types (classes), compile-time Nullable Reference Types (`#nullable enable`), and immutable records with `with` expressions.
What You Will Learn in This Lesson
- Memory architecture: Value types on the Stack vs Reference types on the Managed Heap
- Nullable Reference Types (`string?`) and eliminating NullReferenceExceptions at compile time
- The null-forgiving operator (`!`) and null-coalescing assignment (`??=`)
- Non-destructive mutation on immutable records using the `with` expression
Introduction & Core Concept
C# features a unified, strongly typed type system. All types inherit from System.Object, but are divided into Value Types (stored on the stack or inline) and Reference Types (stored on the managed heap). In modern C#, Nullable Reference Types allow the compiler to enforce null safety across the entire codebase.
WHY DOES THIS MATTER IN THE REAL WORLD?
NullReferenceExceptions have historically been the leading cause of server crashes in production .NET applications. Enabling nullable reference types allows the C# compiler to flag potential null dereferences before code ever reaches staging.
Syntax & Structure
csharp
string nonNull = "Hello";string? nullable = null;var updated = original with { Name = "New" };Compile-Time Null Safety and Record Non-Destructive Mutation
csharpcsharp
123456789101112131415161718192021222324252627282930313233// Nullable Reference Types & Immutable Records in C##nullable enableusing System;public record UserProfile(string Id, string Username, string? Bio, int CreditScore);public class Program{public static void ProcessUser(UserProfile? profile){// 1. Guard check with early returnif (profile is null){Console.WriteLine("Warning: User profile is null.");return;}// 2. Null-coalescing operator with fallbackstring bioSummary = profile.Bio ?? "No public biography provided.";Console.WriteLine($"User: {profile.Username} | Bio: {bioSummary}");// 3. Non-destructive mutation using 'with' expressionvar upgradedUser = profile with { CreditScore = profile.CreditScore + 50 };Console.WriteLine($"Original Score: {profile.CreditScore} | Upgraded: {upgradedUser.CreditScore}");}public static void Main(){var user = new UserProfile("usr_100", "AlexCSharp", null, 740);ProcessUser(user);ProcessUser(null);}}
Line-by-Line Technical Breakdown
1Boxing and Unboxing: Boxing is the process of converting a value type (like int or struct) to System.Object or an interface reference on the heap. Unboxing extracts the value type back from the object reference. Modern C# uses generics and Span<T> to eliminate boxing overhead completely.
Try It Yourself (Interactive Editor)
Modify the code in real-time and click Run to test live browser output and console logs.
Intelligent Code Runner & Live Sandbox[CSHARP]
CSHARP SOURCE EDITOR
Interactive Live CodeCommon Mistakes & How to Avoid Them
#1: Ignoring compiler nullable warnings (#nullable enable) with the null-forgiving operator (!).
The null-forgiving operator (!) suppresses compiler warnings but does not protect against runtime NullReferenceExceptions if the value is actually null.
Incorrect / Antipattern
string name = user.Bio!; // Suppresses warning without checkingCorrect / Professional Solution
string name = user.Bio ?? "Default";Industry Best Practices & Professional Standards
- Enable `<Nullable>enable</Nullable>` in all .csproj project files by default.
- Use `record` for immutable domain entities and request DTOs.
- Use `is null` and `is not null` pattern matching instead of legacy `== null` operator overloads.
Lesson Summary & Core Takeaways
- Value types store data directly; reference types store references to heap objects.
- Nullable Reference Types detect null bugs at compile time.
- Records provide built-in value equality, immutability, and `with` expressions.