Skip to main content

    Final Project • Capstone

    Final Project: Build an Expense Tracker

    By the end of this capstone you'll have built a complete console Expense Tracker from scratch — classes, a List<T> store, a menu loop, LINQ reports, and a path to saving data — pulling together everything the whole C# course has taught you.

    What You'll Build

    • Design a domain model (an Expense class) to represent your data
    • Store many objects in a List<T> and add to it at runtime
    • Drive the program with a menu loop, the spine of every console app
    • Write LINQ queries that total, group, and rank your spending
    • Format a clean, aligned report with currency and dates
    • Plan the extensions: real input, validation, and saving to JSON

    What You'll Practise — and where you learned it

    This project is a victory lap. Each feature below maps straight back to a lesson you've already finished — nothing here is new, it's all combined.

    Feature in the trackerC# skillLesson
    The Expense type (data + constructor)Classes, properties, constructorsOOP
    Storing many expensesList<T>, .Add, .CountCollections
    The menu loopforeach, switchLoops & Control flow
    Totals & category reportsSum, GroupBy, OrderBy, WhereLINQ
    Rejecting bad inputthrow, try / catch, TryParseExceptions
    Saving & loading dataFile, JSON serialisationFiles & JSON

    💡 Real-World Analogy

    Up to now you've been learning the individual instruments — the class drums, the List<T> bass, the LINQ keyboards. A finished program is the band playing together. The tune is the user's journey: open the app, see a menu, add an expense, ask for a report, save and quit. Each instrument you learned has a part to play, and your job in this capstone is to conduct them so they make one coherent piece of music — a real, usable tool.

    How This Build Works

    Real software is never written all at once — you start with a skeleton that runs, then grow it one feature at a time, testing after each. You'll do exactly that here, in three stages:

    • 🧱 Stage 1 — Starter (read & run): a working skeleton with the Expense model, a List<T> store, and a menu loop. One feature (listing) is finished so you can see the shape of the rest.
    • 🎯 Stage 2 — Your turn (two guided steps): fill in the blanks to add expenses to the list, then build a LINQ spending report.
    • 🚀 Stage 3 — Extend it (on your own): a feature checklist with hints but no answers — real input, validation, filtering, and saving to a file.

    Stage 1 — The Starter Skeleton

    Here is the foundation: an Expense class (the domain model), a List<Expense> to hold many of them, and a menu loop that reacts to choices. To keep the output predictable in this runner, the loop walks a fixed script instead of reading the keyboard — when you build the real app you'll swap that one line for Console.ReadLine(). Read every comment, run it, and notice the listing feature already works; the other features are yours to add.

    Worked starter: model + List + menu loop

    Read every comment, run it, and check the output matches the expected block.

    Try it Yourself »
    C#
    using System;
    using System.Collections.Generic;
    
    // === EXPENSE TRACKER — the starter skeleton ===
    // This is the foundation you'll build on. Read it, run it, then in the
    // next two steps you'll add the "add expense" and "report" features.
    
    // 1) The DOMAIN MODEL — one class describing a single expense.
    //    (This is the OOP lesson: data + behaviour bundled into a type.)
    class Expense
    {
        public string Category { get; }   // e.g. "Food", "Travel"
        public decimal Amount { get; }    // mone
    ...

    Stage 2 — Your Turn: Add an Expense

    First feature to build: adding an expense to the store. An AddExpense method needs to do two things — build a new Expense object, then append it to the list with .Add(...). Fill in the two ___ blanks using the hints, then run it; the program will add three expenses and report the count.

    🎯 Your turn: implement AddExpense

    Build the object and Add it to the list, then check three items were stored.

    Try it Yourself »
    C#
    using System;
    using System.Collections.Generic;
    
    class Expense
    {
        public string Category { get; }
        public decimal Amount { get; }
        public DateTime Date { get; }
        public Expense(string category, decimal amount, DateTime date)
        { Category = category; Amount = amount; Date = date; }
        public string Summary() => $"{Date:yyyy-MM-dd}  {Category,-10} £{Amount,8:F2}";
    }
    
    class Program
    {
        static readonly List<Expense> expenses = new List<Expense>();
    
        // 🎯 YOUR TURN — build the "a
    ...

    Stage 2 — Your Turn: Build a LINQ Report

    A list of expenses is only useful once you can summarise it. This is LINQ's moment: Sum gives a grand total, and GroupBy followed by Sum gives a per-category breakdown. Fill in the two ___ blanks (both are the same method!), then run it to see your spending ranked highest-first.

    🎯 Your turn: total and group with LINQ

    Use Sum to total spending, then GroupBy + Sum for a category report.

    Try it Yourself »
    C#
    using System;
    using System.Collections.Generic;
    using System.Linq;                 // LINQ lives here
    
    class Expense
    {
        public string Category { get; }
        public decimal Amount { get; }
        public DateTime Date { get; }
        public Expense(string category, decimal amount, DateTime date)
        { Category = category; Amount = amount; Date = date; }
    }
    
    class Program
    {
        static readonly List<Expense> expenses = new List<Expense>
        {
            new Expense("Food",   12.50m, new DateTime(2026, 6, 1)
    ...

    🔎 Deep Dive: how the pieces connect

    It's worth seeing the whole data flow in one glance. The class is the shape of one record; the list is the store; the methods are the verbs that act on the store; LINQ is how you ask questions of it.

    Expense (class)        ->  one record:  Category, Amount, Date
    List<Expense> expenses ->  the store:    holds many Expense objects
    AddExpense(...)        ->  a verb:       expenses.Add(new Expense(...))
    ListExpenses()         ->  a verb:       foreach over expenses, print
    Report() with LINQ     ->  a question:   expenses.GroupBy(...).Sum(...)
    Save()/Load()          ->  persistence:  List <-> JSON file on disk

    Every console app you ever write follows this same skeleton: a model, a store, verbs that change the store, and queries that read it. Learn it here and you can build almost any small tool.

    Stage 3 — Extend It (on your own)

    No blanks now — just a feature checklist in comments. Turn the starter into a finished, persistent app by adding these one at a time, running after each. Every technique you need comes from a lesson you've already completed, so reach back to those when you're stuck.

    🎯 Extend it: real input, validation, filtering & saving

    Build the five features yourself — hints in comments, no solution given.

    Try it Yourself »
    C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.IO;                   // for file save/load
    // using System.Text.Json;         // uncomment to serialise to JSON
    
    // 🎯 EXTEND IT — turn the starter into a finished app, feature by feature.
    // Pick them off one at a time and run after each. No solution is given —
    // every skill you need is from a lesson you've already completed.
    
    class Expense
    {
        // Already yours from the worked example — reuse it as-is.
        publi
    ...

    Tips for Building Real Projects

    • 💡 Start with something that runs, then grow it. A skeleton you can run beats a perfect plan you can't test. Add one feature, run, repeat.
    • 💡 Keep your model honest: use decimal for money (never double) and a real DateTime for dates — your reports depend on them being correct types.
    • 💡 Validate at the edges: guard AddExpense with a check and a throw, and use TryParse on anything the user typed, so one typo never crashes the app.
    • 💡 Let LINQ do the maths. A GroupBy(...).Sum(...) replaces a dozen lines of manual loops and counters — and reads like the question you're asking.
    • 💡 Commit each stage with Git. Working starter, add feature, report feature — a commit per step gives you a safe point to return to.

    Common Pitfalls (and the fix)

    • "CS0103: The name 'expenses' does not exist in the current context": your List<T> is declared inside one method but used in another. Make it a static field on the class so every method can see it.
    • "CS1061: 'List<Expense>' does not contain a definition for 'Sum'": you forgot using System.Linq; at the top. LINQ methods like Sum, Where, and GroupBy are extension methods that live in that namespace.
    • "System.NullReferenceException": you used an Expense variable that was never created with new. Build the object first, then add it to the list.
    • Money looks wrong (e.g. £12.5 not £12.50): you're printing a raw number. Format it with :F2 or :C$"£{amount:F2}".
    • App crashes on bad input: decimal.Parse("abc") throws. Use decimal.TryParse (and DateTime.TryParse) so invalid input is handled gracefully instead of killing the program.

    📋 Quick Reference — the building blocks

    TaskCode
    Make a storevar list = new List<Expense>();
    Add to itlist.Add(new Expense(...));
    Count itemslist.Count
    Grand totallist.Sum(e => e.Amount)
    Filterlist.Where(e => e.Date.Month == 6)
    Group & totallist.GroupBy(e => e.Category)
    Safe number inputdecimal.TryParse(s, out var n)
    Save to JSONJsonSerializer.Serialize(list)

    Frequently Asked Questions

    Q: Why does the starter use a fixed script instead of Console.ReadLine()?

    So the example produces the same output every time in this in-page runner, which lets you self-check against the expected block. In your own real app on your machine, swap the scripted loop for while (true) reading Console.ReadLine() — that's the first feature in the Extend It step.

    Q: This feels big — where do I start?

    You already started: run the Stage 1 starter, then do the two guided steps. After that, add Extend It features one at a time and run after each. A program is just many small, tested steps stacked up.

    Q: Could I build something other than an expense tracker?

    Absolutely — the skeleton (model → list → menu → LINQ → save) fits a to-do list, a contacts book, a mini inventory, or a habit tracker. Swap the Expense class for your own type and keep the same shape.

    Q: Why decimal for the amount and not double?

    double can't represent values like 0.1 exactly, so money totals drift by tiny fractions. decimal is built for exact base-10 maths, which is what you want for currency. This came up back in the Variables lesson.

    Q: How do I make the data survive after I close the app?

    Serialise the list to JSON and write it to a file on exit, then read and deserialise it on startup — Feature 4 in the Extend It step. That's the difference between a toy and a tool.

    🎉 Course Complete — Congratulations!

    You reached the end of the C# course — and you didn't just read about it, you built with it.

    Look back at how far you've come. Every concept below is now a tool you can pick up and use, and in this capstone you wired them together into a working program:

    • Variables & types — the right type for text, numbers, money, and dates
    • Control flow & loops — the menu loop that drives the whole app
    • Methods — bundling each feature into a named, reusable verb
    • OOP — the Expense class: data and behaviour together
    • Collections — a List<T> storing many objects
    • LINQ — totals, grouping, and ranking your data in a line or two
    • Exceptions — validation that keeps the app alive on bad input
    • Files & JSON — making your data persist between runs

    You can now design a type, store many of them, drive a program with a loop, query data with LINQ, and save it to disk — that's the core of real software. Keep this expense tracker, finish the Extend It features, push it to GitHub, and make it your first portfolio piece. You're ready to build your own projects. 🚀

    🏆 You've completed the entire C# course!

    From variables and loops to OOP, LINQ, exceptions, and files — you've covered the full journey and finished by building something real.

    What's next: finish the Extend It challenge, then start a project of your own. Every skill you've learned is ready to use.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service

    Install LearnCodingFast

    Learn faster with the app on your home screen.