Start learning free

LESSON 560 OF 572 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Inventory Item in C#: Private Stock with Checked Methods

Practice O(1) Read the full explanation

A shop keeps track of how many pieces of each item it has: the item's stock. The stock can never go below 0, and it changes only when pieces are sold or new ones arrive. So the stock is a private field, changed only through two methods that check the rules. The item's name has no rules to protect, so it stays a field any code can read.

Implement the class InventoryItem:

  • InventoryItem(name, stock) creates an item with that name and that many pieces in stock. The name is kept in a field name that other code can read.
  • sell(n) sells n pieces. If n is at least 1 and at most the stock, it lowers the stock by n and returns true. Otherwise it changes nothing and returns false: selling 0 pieces, a negative number of pieces, or more pieces than there are in stock is refused.
  • restock(n) adds n pieces to the stock when n is at least 1, and ignores n otherwise. It returns nothing.
  • getStock() returns the stock. It is the only way for other code to read it.

Keep the stock private the way the Access Modifiers lesson does in your language: self._stock in Python (private by convention), a #stock field in JavaScript, and the private keyword in Java, C++, C#, TypeScript, Kotlin, Scala and Swift. In Kotlin and Scala the constructor's second parameter is named initialStock, and the private stock starts at its value.

Each test case creates one item, then applies a list of operations to it, in order. The output has one line per test case: the item's name and a colon, then what each sell and getStock call returns, separated by spaces, with sell's answer printed as True or False. The starter code spells these names the way your language does: get_stock in Python, Sell, Restock and GetStock in C#.

 

Example 1:

Input:
    InventoryItem("Pencil", 5)
    sell(3)
    getStock()
    sell(5)
    getStock()
    restock(10)
    getStock()
Output: Pencil: True 2 False 2 12
Explanation: Selling 3 of the 5 pencils works and leaves 2. Selling 5 more is refused, because only 2 are left,
and the stock stays 2. restock(10) brings it to 12.

Example 2:

Input:
    InventoryItem("Mug", 4)
    sell(4)
    getStock()
    sell(1)
    getStock()
Output: Mug: True 0 False 0
Explanation: Selling all 4 mugs is allowed and leaves 0. With nothing left, even one mug can't be sold.

Example 3:

Input:
    InventoryItem("Lamp", 2)
    sell(0)
    sell(-3)
    restock(0)
    restock(-5)
    getStock()
    restock(1)
    sell(3)
    getStock()
Output: Lamp: False False 2 True 0
Explanation: Selling 0 or -3 lamps is refused, and restocking 0 or -5 lamps is ignored, so the stock is still 2.
After restock(1) there are 3 lamps, and selling all 3 works.

 

Constraints:

  • A name is one word of English letters. 0 <= stock <= 104 when the item is created.
  • -104 <= n <= 104 in every sell and restock.
  • A test case has from 1 to 1000 operations, and at least one of them is a sell or a getStock.
STEP 1 OF 7
    Ctrl + Enter to check

    C# · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Inventory Item in C#, explained

    Problem overview

    A shop tracks how many pieces of each item it has. The stock can never go below 0, and it changes only when pieces are sold or delivered. The class InventoryItem therefore keeps the stock in a private field and changes it only through two methods that check the rules. The item's name has no rules to protect, so it is a public field.

    • InventoryItem(name, stock) creates an item with that name and that many pieces.
    • Sell(n) sells n pieces and returns true if n is at least 1 and at most the stock. Otherwise it changes nothing and returns false.
    • Restock(n) adds n pieces when n is at least 1, and ignores it otherwise.
    • GetStock() returns the stock.

    For 5 pencils, Sell(3) works and leaves 2. Sell(5) is refused because only 2 are left. Restock(10) then brings the stock to 12.

    Approach

    The key idea is to refuse bad requests before anything changes. In Sell, first test whether the request is invalid: n below 1 (zero or negative pieces make no sense) or above the stock (the shop doesn't have that many). If so, return false and leave the stock alone. Only a request that passes gets to the line that lowers the stock, so the stock can't become negative.

    Because the check comes first, the method needs no undo step, and every call is O(1). Selling exactly the whole stock is allowed: n equal to the stock passes the check and leaves 0.

    Step by step

    1. Declare public string name. Other code may read the name directly.
    2. Declare private int stock. Only code inside the class can use it; outside, item.stock is a compile error.
    3. Constructor: store both parameters with this.name and this.stock. The parameters share the fields' names, so this. picks the fields.
    4. In Sell, write an if for n < 1 || n > stock joined with ||. Its body returns false.
    5. After the if, lower the stock by n and return true.
    6. In Restock, add n to the stock only if n >= 1. Zero or a negative number isn't a delivery.
    7. GetStock returns the stock. It is the only way for other code to read it.

    The solution in C#

    class InventoryItem {
        public string name;
        private int stock;
        public InventoryItem(string name, int stock) {
            this.name = name;
            this.stock = stock;
        }
        public bool Sell(int n) {
            if (n < 1 || n > stock) {
                return false;
            }
            stock -= n;
            return true;
        }
        public void Restock(int n) {
            if (n >= 1) {
                stock += n;
            }
        }
        public int GetStock() {
            return stock;
        }
    }
    

    Using it:

    var p = new InventoryItem("Pencil", 5);
    Console.WriteLine(p.Sell(3));
    Console.WriteLine(p.GetStock());
    Console.WriteLine(p.Sell(5));
    Console.WriteLine(p.GetStock());
    p.Restock(10);
    Console.WriteLine(p.GetStock());
    

    This prints:

    True
    2
    False
    2
    12
    

    C# writes a bool as True or False when it is printed, and the lesson's tests print the answers the same way.

    Details worth knowing

    • Public and private together. name is public, so p.name gives "Pencil". p.stock does not compile, because the field is private.
    • The || operator. It stops as soon as the left side is true. For a request of -3, the first test already decides, and the second test is not evaluated.
    • Return values carry the outcome. Sell returns a bool so callers know whether the sale happened. Restock returns nothing: ignoring a bad delivery is silent by design.
    • Refused calls change nothing. After a failed Sell, GetStock() returns what it did before the call.

    Edge cases and common mistakes

    • Selling everything. A Sell of the full stock returns true and leaves 0. Writing n >= stock as the refusal would wrongly refuse it. With a stock of 4 mugs, Sell(4) gives True and stock 0, and the next Sell(1) gives False.
    • Zero and negative amounts. For a lamp with stock 2, Sell(0) and Sell(-3) return False, and Restock(0) and Restock(-5) change nothing, so the stock is still 2. A negative sale would otherwise increase the stock, and a negative restock would decrease it.
    • Changing before checking. Lowering the stock first and testing afterwards leaves a negative stock behind when the test fails.
    • Using && instead of ||. A request is invalid if either condition holds; no number is both below 1 and above the stock.
    • Restock then sell. After Restock(1) on the lamp there are 3, and Sell(3) returns True and leaves 0.

    Testing

    • Pencil with 5: Sell(3) True, stock 2, Sell(5) False, stock 2, Restock(10), stock 12.
    • Mug with 4: Sell(4) True, stock 0, Sell(1) False, stock 0.
    • Lamp with 2: Sell(0) and Sell(-3) False; Restock(0) and Restock(-5) ignored; stock 2; Restock(1); Sell(3) True; stock 0.

    Why private fields need methods

    Making stock private is only half of the design. The other half is that the class offers exactly the operations a shop needs, each with its rule. Code outside can ask to sell, ask to restock and ask for the number, but it can never set the stock to -7 or to a number that doesn't match what really happened.

    Compare the alternative, a public stock field. Every place that sells something would repeat the test n <= stock, and a single place that forgets it can put the item in an invalid state. With the private field, the rules live in two short methods, and they are the only places to read when something looks wrong.

    The name is public because nothing can go wrong with it: any value is a valid name. Choosing what to protect, and leaving the rest simple, is part of the design.

    Key takeaways

    • Check the request first, change the state second.
    • Return a bool when the caller needs to know whether an operation happened.
    • Protect fields that have rules, and leave harmless ones public.
    Keep going with C#500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free