Start learning free

LESSON 558 OF 572 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Ticket Numbers in C#: Static Members and a Shared Counter

Practice O(1) Read the full explanation

A ticket machine gives every new ticket the next number: the first ticket gets 1, the next one 2, and so on. The counter belongs to the class, not to any one ticket: it is a static member of Ticket, one copy shared by all the tickets. Each ticket keeps its own number, copied from the counter when the ticket is created.

Implement the class Ticket:

  • Ticket(name) creates a ticket for name. It adds 1 to the class-level counter and gives the new ticket that value as its number. The ticket keeps its name and its number in two fields, name and number.
  • The static method issued() returns how many tickets were created since the counter was last reset.
  • The static method resetCounter() sets the counter back to 0, so the next ticket gets number 1 again.

For each test case, the test code calls resetCounter() through the class name, then creates one ticket per name, in order. Once all the tickets of the case exist, it prints each ticket as its name, a space, # and its number, one ticket per line, and then the value of issued() on a line of its own.

The starter code spells these names the way your language does: reset_counter in Python, Issued and ResetCounter in C#. In Python the counter is a class attribute and the two methods are marked @staticmethod; in Kotlin and Scala the counter and the two methods live in the companion object, as in the Static Members lesson.

 

Example 1:

Input:
    Ticket("Ann")
    Ticket("Bob")
    Ticket("Cy")
Output:
Ann #1
Bob #2
Cy #3
3
Explanation: resetCounter() set the counter to 0. Each new ticket adds 1 to it and keeps the new value,
so the tickets get 1, 2 and 3, and issued() returns 3.

Example 2:

Input:
    Ticket("Mia")
    Ticket("Mia")
Output:
Mia #1
Mia #2
2
Explanation: The number comes from the shared counter, not from the name, so the two tickets for Mia
get different numbers. The numbers start at 1 again because resetCounter() ran before this case.

Example 3:

Input:
    (no tickets)
Output:
0
Explanation: resetCounter() set the counter to 0 and no ticket was created, so issued() returns 0.

 

Constraints:

  • A test case creates from 0 to 1000 tickets.
  • A name is one word of 1 to 20 English letters. Two tickets can have the same name.
  • The tickets are printed only after all of them were created, so every ticket must store its own number: reading the shared counter when printing would give every ticket the last number.
STEP 1 OF 7
    Ctrl + Enter to check

    C# · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Ticket Numbers in C#, explained

    Problem overview

    A ticket machine gives each new ticket the next number: 1, then 2, then 3. The class Ticket models it. Each ticket keeps its own name and number. The counter that hands out the numbers does not belong to any one ticket: it belongs to the class, and there is exactly one copy of it. The static method Issued() returns how many tickets were created since the last reset, and the static method ResetCounter() sets the counter back to 0.

    After a reset, creating tickets for Ann, Bob and Cy gives them the numbers 1, 2 and 3, and Issued() returns 3. Two tickets for the same name still get different numbers, because the number comes from the counter, not from the name.

    Approach

    C# has two kinds of members. An instance member, such as name, exists once per object. A static member, marked with static, exists once per class and is shared by every object. The counter must be static: if it were an ordinary field, each new ticket would get a fresh counter starting at 0 and every ticket would be number 1.

    The constructor does two things for each new ticket: it adds 1 to the shared counter, then copies the counter's new value into the ticket's own number field. The copy matters. The counter keeps changing as more tickets are made, but a ticket's number must stay what it was when the ticket was created. Reading the counter later, instead of copying it, would give every ticket the last number.

    Step by step

    1. Declare the counter at the top of the class: public static int Count = 0;. One copy for the whole class.
    2. Declare the per-ticket fields: a public string name and a public int number. They are not static, so every ticket has its own.
    3. Store the name in the constructor with this.name = name.
    4. Increase the counter with Count++. Inside the class you can write just Count; from outside it is Ticket.Count.
    5. Copy it into this.number. After a reset, the first ticket finds the counter at 1 here, so numbers start at 1.
    6. Issued returns Count.
    7. ResetCounter assigns 0 to Count, so the next case numbers its tickets from 1 again.

    The solution in C#

    class Ticket {
        public static int Count = 0;
        public string name;
        public int number;
    
        public Ticket(string name) {
            this.name = name;
            Count++;
            this.number = Count;
        }
    
        public static int Issued() {
            return Count;
        }
    
        public static void ResetCounter() {
            Count = 0;
        }
    }
    

    Using it:

    Ticket.ResetCounter();
    var a1 = new Ticket("Ann");
    var a2 = new Ticket("Bob");
    var a3 = new Ticket("Ann");
    Console.WriteLine(a1.name + " #" + a1.number + ", " + a2.name + " #" + a2.number + ", " + a3.name + " #" + a3.number);
    Console.WriteLine(Ticket.Issued());
    Ticket.ResetCounter();
    Console.WriteLine(Ticket.Issued() + " " + new Ticket("Cy").number);
    

    This prints:

    Ann #1, Bob #2, Ann #3
    3
    0 1
    

    The last line shows the reset: the count is 0 until a ticket is made, and the next ticket is number 1 again.

    Details worth knowing

    • Calling static members. You call them on the class name: Ticket.Issued(), with no ticket needed. You can't call a1.Issued(); C# reports an error for a static member used through an object.
    • Static methods can't use this. A static method runs without any particular ticket, so it can use only static members. That is fine here, since Issued and ResetCounter only touch Count.
    • Instance code can use static members. The constructor reads and writes Count without any prefix, because every ticket can see its class's shared members.
    • The static counter lives as long as the program, not as long as any ticket. Creating tickets always continues from the current value, which is why a reset is needed between independent cases.

    Edge cases and common mistakes

    • Making the counter an instance field. Every ticket would start from 0, and every number would be 1.
    • Not copying the value. A number that is read from Count when printing, instead of stored at creation, would show the last number for every ticket.
    • Incrementing in the wrong order. Copying the counter before Count++ would number the first ticket 0.
    • No tickets. After a reset with no tickets created, Issued() returns 0.
    • Same name, different tickets. Two tickets for "Mia" are separate objects and get numbers 1 and 2.

    Testing

    • Reset, then Ann, Bob, Cy: Ann #1, Bob #2, Cy #3, and Issued() is 3.
    • Reset, then Mia and Mia: Mia #1, Mia #2, and Issued() is 2.
    • Reset and no tickets: Issued() is 0.

    Static or instance: how to decide

    Ask whether a value describes one object or the whole class. A ticket's name and number describe that ticket, so they are instance fields. The count of tickets made so far describes the machine, so it is static. The same question applies to methods: Issued and ResetCounter need no particular ticket, so they are static, while a method that read a ticket's own number would be an instance method.

    One consequence is that a static field can be shared by code that never creates an object. Ticket.ResetCounter() works before any ticket exists, which is exactly how the lesson's tests start each case.

    Keep going with C#500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free