C# Programming Tutorial 0/45 lessons ~6 min read Lesson 4

    Variables and Data Types

    Variables store state in memory.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Variables store state in memory. C#'s static type system assigns every variable a compile-time type — int, decimal, string, or custom types — catching bugs before deployment. Understanding value types vs reference types is the single most important concept for interview success.

    Modern C# adds var for local type inference, required members, records for immutable data, and nullable reference annotations. Financial and healthcare systems rely on decimal for money — never float — and explicit DateTimeOffset for audit trails.

    This lesson covers primitives, strings, var rules, const vs readonly, and boxing pitfalls that still appear in senior .NET interviews.

    The story

    A digital wallet app stores each account snapshot with a unique ID, a balance in dollars and cents, and the exact moment the snapshot was taken. Using decimal for money avoids the rounding errors you get with double — a bug that has caused real financial discrepancies in production systems.

    When the user receives a $100.50 bonus, the app creates a new snapshot rather than mutating an old one, preserving an audit trail regulators expect from banking software.

    Understanding the topic

    Key concepts

    • Value types (int, bool, struct) live on the stack or inline in objects; copying copies data.
    • Reference types (class, string, array) hold references to heap objects; copying copies the reference.
    • var requires initializer — compiler infers type; locals still strongly typed.
    • decimal is 128-bit floating point ideal for currency; double for scientific math.
    • Nullable value types (int?) and nullable reference types (string?) express absence.
    • const compile-time constants; readonly set once at construction.
    text
    classDiagram
    class ValueTypes {
    int
    double
    bool
    struct
    }
    class ReferenceTypes {
    string
    object
    class
    array
    }

    Step-by-step explanation

    1. Declare: type name = value; or var name = value;
    2. Compiler verifies assignments match declared type.
    3. Value type assignment duplicates bits; reference assignment aliases same object.
    4. Boxing wraps value types in object on heap — avoid in hot loops.
    5. string is immutable — concatenation in loops uses StringBuilder.
    6. Default values: 0, false, null (references), default struct fields zeroed.

    Practical code example

    Banking-style variables with decimal, DateTimeOffset, record, and nullable annotations:

    csharp
    namespace TechLearningPro.Variables;
    public record AccountSnapshot(Guid Id, decimal Balance, DateTimeOffset AsOf);
    public class VariableDemo
    {
    public static AccountSnapshot CreateSnapshot(decimal openingBalance)
    {
    const string Currency = "USD";
    var accountId = Guid.NewGuid();
    decimal balance = openingBalance;
    DateTimeOffset asOf = DateTimeOffset.UtcNow;
    balance += 100.50m; // m suffix = decimal literal
    return new AccountSnapshot(accountId, balance, asOf) with { };
    }
    }

    Line-by-line code explanation

    • public record AccountSnapshot(...) defines an immutable data shape with value-based equality — ideal for DTOs.
    • Guid Id stores a globally unique identifier for the account snapshot.
    • decimal Balance holds money precisely — never use double for currency.
    • DateTimeOffset AsOf captures when the snapshot was taken with timezone awareness.
    • const string Currency = "USD" declares a compile-time constant that cannot change at runtime.
    • var accountId = Guid.NewGuid() generates a fresh unique ID for each new snapshot.
    • decimal balance = openingBalance copies the starting balance into a local variable you can modify.
    • balance += 100.50m adds a deposit — the m suffix marks a decimal literal.
    • DateTimeOffset.UtcNow records the current UTC timestamp for API consistency.
    • return new AccountSnapshot(...) with { } creates a record copy with updated field values.

    Key takeaway: Always suffix decimal literals with m. Use DateTimeOffset.UtcNow for APIs storing timestamps. Records give value-based equality for DTOs.

    Real-world use

    Where you'll use this in production

    • Ledger systems storing decimal amounts with invariant culture formatting.
    • Patient vitals as structs for low-allocation telemetry buffers.
    • Configuration DTOs as records passed through ASP.NET Core pipelines.
    • Desktop apps binding ViewModel properties with INotifyPropertyChanged.

    Best practices

    • Use decimal for money; never float or double for currency.
    • Prefer DateTimeOffset over DateTime for APIs and logs.
    • Enable nullable reference types; use ? and ! consciously.
    • Use var when type is obvious from right-hand side.
    • Prefer readonly fields over mutable public fields.
    • Use records for immutable data transfer objects.

    Common mistakes

    • Using float for money — rounding errors in payroll.
    • Assuming string concatenation is cheap in tight loops.
    • Uninitialized local variables — compile error CS0165.
    • Confusing == on boxed value types with reference equality.
    • Using var without initializer — CS0818.

    Advanced interview questions

    Q1BeginnerValue type vs reference type?
    Value types copy data; reference types copy references pointing to heap objects.
    Q2BeginnerWhy decimal for financial calculations?
    Exact base-10 representation avoids binary floating-point rounding errors.
    Q3IntermediateWhat is boxing?
    Wrapping a value type in object/interface reference, allocating on heap.
    Q4IntermediateDifference between const and readonly?
    const compile-time constant; readonly set in constructor or field initializer, runtime.
    Q5AdvancedExplain nullable reference types and their compile-time benefit.
    Annotations (string?) enable flow analysis — compiler warns on possible null dereference before runtime NullReferenceException.

    Summary

    C# variables are statically typed — compiler enforces correctness. Value vs reference semantics affect copying, equality, and GC pressure. decimal and DateTimeOffset are enterprise defaults for money and time. var infers types; nullable annotations prevent null bugs. Next: operators for arithmetic, comparison, and logical expressions.

    Ready to mark this lesson complete?Track your journey across the entire course.