Featured resource
2026 Tech Forecast
2026 Tech Forecast

1,500+ tech insiders, business leaders, and Pluralsight Authors share their predictions on what’s shifting fastest and how to stay ahead.

Download the forecast
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • Core Tech
Labs

Trace C# Objects from Construction to Correction

Riverside Diner's payroll clerk has escalated a ticket: hourly employees who work overtime are getting shorted on their paychecks. You are the developer assigned to the small C# console tool that models each worker as an Employee object and computes weekly wages from hourly rate and hours worked. The codebase currently has no working constructor, no way to build a roster of real employees, and no way to turn the timesheet numbers typed at the console into usable constructor and method arguments. Worse, the one wage formula that exists is quietly wrong for anyone who works more than 40 hours. Over the course of the lab you build the Employee type correctly from the ground up, populate and query a roster of employees through their public methods, teach the program to parse console input into the numeric values the objects need, add a lightweight state tracer that lets you watch an employee's fields change across a pay computation the way stepping through code in Visual Studio would, and finally use those traced values to pinpoint and correct the overtime bug so every paycheck comes out right.

Lab platform
Lab Info
Level
Beginner
Last updated
Oct 05, 2026
Duration
45m

Contact sales

By clicking submit, you agree to our Privacy Policy and Terms of Use, and consent to receive marketing emails from Pluralsight.
Table of Contents
  1. Challenge

    Step 1: Meet the Riverside Diner payroll bug

    The ticket

    Riverside Diner's payroll clerk has escalated a bug: hourly employees who work overtime are getting shorted on their paychecks. The diner's small C# console tool models each worker as an Employee object and calculates weekly wages from an hourly rate and hours worked, but the codebase you've inherited is unfinished in more places than the one bug report mentions.

    You're the developer assigned to fix it -- and to fix it properly, you first have to get the object model itself working. ## The codebase you're inheriting

    Open src/ and you'll find six files, each with // TODO markers where work is missing:

    • Employee.cs -- the Employee class has fields for Name, HourlyRate, and HoursWorked, but no constructor to set them and no methods to report on them.
    • Roster.cs -- meant to build a list of real employees and total their pay, currently empty.
    • InputParser.cs -- meant to turn console-typed text into the numbers Employee needs.
    • StateTracer.cs -- meant to log an employee's field values step by step, the way a debugger would.
    • WageCalculator.cs -- already computes a wage from rate and hours... except it quietly pays every hour at the same rate, overtime included.
    • PayrollReport.cs -- meant to turn a whole roster into a readable, correct report.

    Each file compiles as-is, but the TODO comments mark exactly what you'll complete. ## The plan

    You'll work through the codebase in the order a real fix would demand:

    • Step 2 -- give Employee a working constructor and a first method that proves its fields were actually set.
    • Step 3 -- build a roster of real employees and combine their individual pay summaries into a payroll total.
    • Step 4 -- parse raw console-style input into the numbers those objects need, and add a state tracer that shows an employee's fields evolving during a pay computation.
    • Step 5 -- use exactly those traced values to pinpoint the overtime bug in WageCalculator.cs, fix it, and confirm the fix through the full payroll report.

    By the end, every paycheck Riverside Diner generates will match what its employees actually earned. ## Running the checks

    Each step's work is verified by an automated test file. From the project root you can run the full suite at any point with:

    dotnet test tests/Lab.Tests.csproj --nologo --verbosity quiet
    

    Run it after every task -- a passing test is your signal that a piece of the payroll tool now behaves the way Riverside Diner needs it to. Head into Step 2 to start with the piece everything else depends on: an Employee that actually knows its own data.

    If you get stuck, you can refer to the provided solution code for each task, available in the solution folder.

    info> This lab experience was developed by the Pluralsight team using an internally developed AI tool. All sections were verified by human experts for accuracy prior to publications. However, content may still contain errors or inaccuracies, and we recommend independent verification.

    To report a problem or provide feedback, click here. Feedback may be used to improve accuracy in accordance with our Privacy Policy.

  2. Challenge

    Step 2: Give every Employee a defining constructor

    Constructors and field initialization

    A class's fields only hold real data if something assigns them. In C#, that something is almost always the constructor: a method with the same name as the class, run automatically by new, whose job is to take incoming parameters and store them into the object's fields so every instance starts fully formed.

    Right now, new Employee("Jamie Ruiz", 14.75, 38) in src/Employee.cs would compile only once a matching constructor exists -- and until that constructor assigns its parameters to Name, HourlyRate, and HoursWorked, every new employee starts with nothing. ## Proving it with an instance method

    A constructor that silently sets fields is hard to trust -- you need a way to look at the result. That's what instance methods are for: called on a specific object through dot notation (employee.Describe()), they can read that object's own fields and hand back something you can inspect.

    With the constructor in place, the next job is a method that turns an Employee's three fields into one readable line, so a single call proves the constructor did its job correctly.

  3. Challenge

    Step 3: Populate and query a roster of employees

    Calling methods through dot notation

    With a constructor and Describe() working, Employee is ready to do real payroll work. src/Employee.cs already has a WageCalculator.ComputeWeeklyWage(hourlyRate, hoursWorked) helper available to call -- it computes a wage, even though (as the ticket warns) it isn't yet doing that correctly for every case.

    Your next job is a method that combines an employee's name with that computed wage, the same way Describe() combined name, rate, and hours -- another instance method reached through employee.GetPaySummary(). ## From one employee to a roster

    A single Employee object proves the class works; a diner's payroll needs many of them. src/Roster.cs is where you move from constructing one object at a time to building a collection -- a List<Employee> -- that represents everyone on staff.

    This is also where the overtime bug becomes visible in the data: the roster needs at least one employee whose hours push past 40, since that's exactly the case WageCalculator currently mishandles. ## Aggregating across the roster

    Once you can build the roster, the payroll clerk's real question is simple: what does the diner owe this week, in total? That means looping over every Employee in the list and adding each one's wage into a single running number, rather than reporting them one at a time.

  4. Challenge

    Step 4: Turn console input into numbers and trace state

    Numeric parsing: double.TryParse

    Everything typed at a console -- or read from a timesheet form -- arrives as a string, but Employee's constructor needs a double for the hourly rate. double.TryParse converts text to a number without throwing when the text is malformed; it returns true or false and writes the parsed value into an out parameter, so you can fall back to a safe default instead of crashing on a clerk's typo.

    src/InputParser.cs is where that conversion happens for hourly rate. ## Numeric parsing: int.Parse

    Hours worked, by contrast, are recorded as whole numbers, and there's no sensible default to fall back to if the text is garbage -- an unreadable hours entry is a data problem worth surfacing loudly. int.Parse does exactly that: it converts text to an int and throws an exception if the text isn't a valid whole number, instead of quietly returning zero.

    InputParser.cs needs that same conversion for hours worked, deliberately using the stricter of the two parsing styles. ## State tracing: watching fields change

    When a bug involves a value computed from other values -- exactly the overtime situation here -- the fastest way to find it is to watch the inputs and the output side by side, the way stepping through code in a debugger shows a variable's value at each line. src/StateTracer.cs builds a lightweight version of that: a method that reads an Employee's fields and the wage WageCalculator produces from them, and returns each as a labeled log entry in sequence.

    That log is what you'll use in Step 5 to catch the bug in the act.

  5. Challenge

    Step 5: Diagnose and correct the wage formula

    Diagnosing the arithmetic

    Run the tracer from Step 4 against an employee with more than 40 hours and the log tells the story plainly: the wage entry grows by exactly hourlyRate for every hour past 40, when it should grow by 1.5 * hourlyRate. src/WageCalculator.cs is paying overtime hours at the same straight-time rate as regular hours -- the formula never splits the two.

    Fixing it means separating hoursWorked into a regular portion capped at 40 and an overtime portion for anything beyond, paying each at its own rate. ## Wiring the fix into the report

    A correct WageCalculator only matters if the payroll clerk actually sees correct numbers. src/PayrollReport.cs is the last piece: a method that turns the whole roster into the multi-line report the clerk reads every week, built from the GetPaySummary() calls you already wrote in Step 3 -- now backed by the fixed formula. ## Confirming the fix reached everyone

    One correct paycheck isn't proof the bug is gone -- the fix needs to hold across the whole roster, including employees who never work overtime at all. A final method in PayrollReport.cs totals up exactly how much extra pay the overtime fix added across every employee, so a roster with no overtime workers reports zero and a roster like the one from Step 3 reports a real, positive premium.

  6. Challenge

    Step 6: Run the application

    Every task is done, and each one was graded the moment you completed it. What you have not done yet is watch the whole application run at once -- which is the only place the pieces you wrote separately become a single working program.

    Start the application

    Open the Terminal tab and run:

    dotnet run --project src/Lab.csproj
    

    The program runs in the terminal and prints its output there. Every behaviour it shows is code you wrote in the previous steps, so read the output against what each task asked for -- that is the whole lab, working as one program. ### Run the checks yourself

    The lab ran each task's test for you as you went, but they are ordinary tests and you can run them whenever you like. The whole suite:

    dotnet test tests/Lab.Tests.csproj --nologo --verbosity quiet
    

    Or one task at a time:

    bash runTest.sh Task_2_1
    

    Each failure names the task it belongs to, so the output tells you which step to go back to rather than which line to stare at. Two things worth trying before you finish: break something on purpose and watch the matching check fail, then put it back. Knowing what a failure looks like is worth as much as knowing what a pass looks like, and it costs you nothing here.

    When you are done, everything you wrote is still in the editor tabs -- the lab is yours to keep reading.

About the author

Pluralsight’s AI authoring technology is designed to accelerate the creation of hands-on, technical learning experiences. Serving as a first-pass content generator, it produces structured lab drafts aligned to learning objectives defined by Pluralsight’s Curriculum team. Each lab is then enhanced by our Content team, who configure the environments, refine instructions, and conduct rigorous technical and quality reviews. The result is a collaboration between artificial intelligence and human expertise, where AI supports scale and efficiency, and Pluralsight experts ensure accuracy, relevance, and instructional quality, helping learners build practical skills with confidence.

Real skill practice before real-world application

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight