Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close
    Lesson17 / 20

    Build your Study Planner: add, list and complete tasks

    Can you build the planner without copying the whole answer at once? Work through three checkpoints: a menu, a task list, and a completion command.

    Plan the behaviour before the code

    The first version keeps tasks in memory. A learner can type a to add, l to list, d to mark a numbered task done, and q to quit. Commands are the lowercase letters shown in the menu. Blank titles and invalid task numbers are rejected. Closing this version loses its tasks; the next lesson adds saving.

    Text
    read command
        │
        ├─ a ──> validate title ──> add task
        ├─ l ──> show numbered tasks
        ├─ d ──> validate number ──> mark item done
        └─ q / end of input ──> finish
    
    After a, l or d: return to the menu

    Before looking at the implementation, draw three task boxes on paper. Give each a Title and an IsDone flag. The list holds references to those objects. The displayed task numbers start at 1; the list indexes start at 0.

    This version keeps the StudyTask declaration small and has no explicit constructor. C# supplies a parameterless constructor. The form new StudyTask { Title = title.Trim() } creates an object and then sets its writable Title property; the braces are an object initializer. IsDone starts false, the default bool value.

    The screen shows task 1. Which list index selects it after validating the number?

    A 1
    B 0
    C tasks.Count
    D -1
    Show answer

    Correct answer: B

    Subtract one from the learner-facing number: 1 - 1 = 0.

    Option A: Index 1 means the second item.

    Option C: Count is past the last valid index.

    Option D: Negative indexes are invalid.

    Hint: User numbering and list indexing start at different values.

    Build it in small passes

    The condition while (true) keeps the menu loop running. The break statement leaves that loop when q is entered or input ends. command == null detects end of input, and || accepts either exit condition. A return inside AddTask leaves that method and returns to the menu; it does not leave the outer loop.

    Create a separate console project in a new folder named StudyPlannerApp. Build one checkpoint at a time; the complete program below is a reference to compare with after an attempt.

    CheckpointBuild these piecesTry it before continuing
    1. A menu that stopsThe menu loop and q/end-of-input branchEnter q. You should see Goodbye. and the process should finish.
    2. Tasks you can add and listStudyTask, AddTask and ShowTasks; connect a and l in the menuList an empty plan, reject a blank title, then add Read C# and list it.
    3. A task you can completeMarkDone; connect d in the menuReject task 0 without changing state. Complete task 1, then list it again.

    At checkpoint 1, include only the menu and its exit branch; do not call AddTask, ShowTasks or MarkDone yet. At checkpoint 2, add the StudyTask class and the two methods before connecting a and l. At checkpoint 3, add MarkDone before connecting d. This keeps every checkpoint buildable without empty placeholder methods. Run each row’s check before adding the next command.

    Try the complete session

    Read the program. Before running, predict the list after entering these lines, one at a time:

    Text
    a
    Read C#
    l
    d
    1
    l
    q

    Complete Program.cs — compare after your checkpoints

    This is a complete replacement for Program.cs. Keep one copy of each method; do not append it to your current program.

    C#
    using System;
    using System.Collections.Generic;
    
    List<StudyTask> tasks = new List<StudyTask>();
    Console.WriteLine("Study Planner");
    while (true)
    {
        Console.WriteLine("a=add l=list d=done q=quit");
        string? command = Console.ReadLine();
        if (command == null || command == "q")
        {
            Console.WriteLine("Goodbye.");
            break;
        }
        if (command == "a") AddTask(tasks);
        else if (command == "l") ShowTasks(tasks);
        else if (command == "d") MarkDone(tasks);
        else Console.WriteLine("Unknown command.");
    }
    
    static void AddTask(List<StudyTask> tasks)
    {
        Console.WriteLine("Task title:");
        string? title = Console.ReadLine();
        if (string.IsNullOrWhiteSpace(title))
        {
            Console.WriteLine("Title required.");
            return;
        }
        tasks.Add(new StudyTask { Title = title.Trim() });
        Console.WriteLine("Added.");
    }
    
    static void ShowTasks(List<StudyTask> tasks)
    {
        if (tasks.Count == 0)
        {
            Console.WriteLine("No tasks yet.");
            return;
        }
        for (int i = 0; i < tasks.Count; i++)
        {
            string status = "todo";
            if (tasks[i].IsDone) status = "done";
            Console.WriteLine($"{i + 1}. [{status}] {tasks[i].Title}");
        }
    }
    
    static void MarkDone(List<StudyTask> tasks)
    {
        Console.WriteLine("Task number:");
        string? text = Console.ReadLine();
        if (!int.TryParse(text, out int number) || number < 1 || number > tasks.Count)
        {
            Console.WriteLine("Invalid task number.");
            return;
        }
        tasks[number - 1].IsDone = true;
        Console.WriteLine("Completed.");
    }
    
    class StudyTask
    {
        public string Title { get; set; } = "";
        public bool IsDone { get; set; }
    }

    In the predicted session, the first list shows 1. [todo] Read C#; the second shows 1. [done] Read C#. The MarkDone method changes the object stored in the list. It does not remove the task.

    Why does AddTask return early when the title is blank?

    A It prevents an invalid task from being added
    B It exits the whole application immediately
    C It clears the existing tasks
    D It saves the list to a file
    Show answer

    Correct answer: A

    The method stops before tasks.Add. Control returns to the menu loop.

    Option B: return here exits AddTask, not the outer program.

    Option C: There is no Clear call.

    Option D: This version has no persistence.

    Check the contract

    Try thisExpected result
    List immediatelyNo tasks yet.
    Add a title containing only spacesTitle required; no item added.
    Add Read C#, then listOne todo item.
    Complete task 0, text abc or a number beyond CountInvalid task number; existing state preserved.
    Complete task 1, then listThe same item is now done.
    End input at the menuThe application exits.

    Which check best verifies that an invalid task number is harmless?

    A Only check that the menu is printed
    B Enter an invalid number, then list and inspect the original task state
    C Only check that the program compiles
    D Rename the tasks variable
    Show answer

    Correct answer: B

    The requirement is about preserving state, so inspect that state after the rejected action.

    Option A: A menu alone does not show whether data changed.

    Option C: Compilation cannot prove the validation behaviour.

    Option D: A name change does not test anything.

    Your turn: add a useful command

    Add c to count completed tasks without changing any tasks. Test one todo task and one done task; the result should be 1. Use a foreach loop and increase a counter only when IsDone is true. You already know every required building block. Add the command to the menu text as well as to the decision chain.

    Explain your application

    Describe one complete journey from reading d to changing IsDone. Name the input validation, the conversion from number to index, the changed object and the return to the menu. Keep this first version small enough that you can explain each method.

    Reference: Microsoft — List<T>.

    Quick reference

    • Write the behaviour before the implementation.
    • Build the menu, then add one command at a time.
    • Validate a task number before subtracting one and indexing.
    • Keep each method focused.
    • Test what happens to state after invalid input.
    Sign in to mark lessons done and keep your place in the course.Sign in

    TechInterviewNotes Editorial Team · Updated 27 Oct 2026 ·