question

RonaldRex-8389 avatar image
0 Votes"
RonaldRex-8389 asked RonaldRex-8389 edited

Interfaces

I was wanting to know is there anyone that is well versed in C# Interfaces and OOP design. Here is my problem. Say for instance I have a pizza ordering system and I have different menu items that a customer can order. For example, pizzas, drinks, salads, and desserts. I want to just start with this small piece of the problem and thats that we all know that pizzas, drinks and salads come in different sizes but if I could have a method that all of these items share a common interface with then if I had a method that I could pass a type IMenuItem into for example and it was able to return the price of every item regardless of whether it was a pizza, drink, salad, or dessert. Can someone help me with how this method that takes an Interface as a parameter should be approached, maybe a small code example. Thanks for any help offered.

dotnet-csharpdotnet-maui
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

Paul-5034 avatar image
0 Votes"
Paul-5034 answered RonaldRex-8389 edited

The "size" of a menu item relates more to a purchase rather than the menu item itself, so it makes sense to do the price calculation outside of the actual menu item. In fact you could just use each IMenuItem as a place to store the supported sizes (along with the prices) and calculate it in your business layer, or if you had an ItemPurchase that has two properties: Item (of type IMenuItem) and Size (of type ItemSize), then that calculation could just live inside there.

Pizza pizza = new Pizza(new Dictionary<ItemSize, decimal>() {
    { ItemSize.Small, 10 },
    { ItemSize.Medium, 20 },
    { ItemSize.Large, 30 },
});

PrintPrice(pizza, ItemSize.Medium);

decimal? GetItemPrice(IMenuItem item, ItemSize size) {
    if (!item.Prices.ContainsKey(size)) {
        return null;
    }

    return item.Prices[size];
}

void PrintPrice(IMenuItem item, ItemSize size) {
    decimal? price = GetItemPrice(item, size);

    if (price is null) {
        Console.WriteLine($"Can't buy this item in a {size}");
        return;
    }

    Console.WriteLine($"That'll cost {price}");
}

enum ItemSize {
    Small, Medium, Large
}

interface IMenuItem {
    IReadOnlyDictionary<ItemSize, decimal> Prices { get; }
}

class Pizza : IMenuItem {
    public Pizza(IReadOnlyDictionary<ItemSize, decimal> prices) {
        Prices = prices;
    }

    public IReadOnlyDictionary<ItemSize, decimal> Prices { get; }
}
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for your help. I was wondering why did you use a dictionary and why did you use an enum? Thanks !!!

0 Votes 0 ·

Dictionary<ItemSize, decimal> is just a convenient way to map all ItemSizes to their corresponding prices (the decimal) for that product.

If pizza.Prices doesn't contain a mapping for the ItemSize you're searching for then that implies that the specific product isn't available in that size.

An enum represents one of several discrete values, or "nominal" data (i.e. labels referencing specific sizes). Enum values do have underlying numerical values that increment in the order they're specified (i.e. Small = 0, Medium = 1, Large = 2, in this example) but as a developer you can choose what these labels actually represent.

Pizzas are usually measured in inches, drinks are usually measured in fluid ounces and salads would probably be measured in something a bit more woolly, like the labels used for the ItemSize enum. For simplicity I used the latter option for each item.

In a real world application you'd likely not use an enum & instead store the sizes in the database with the items themselves, so the database can be the single source of truth in your system. You could even have different size scales if you store them in your database (i.e. '10 in.', '12 in.', '14 in.' for pizza, '7 oz', '12 oz', '32 oz' for drinks, 'small', 'medium', 'large' for salads).

1 Vote 1 ·

Excellent. Thanks for helping me out. Happy Holidays !!!

0 Votes 0 ·

One more question I noticed that you left off the access modifiers for the interface IMenuItem and the IReadOnyDictionary. Do you mind explaining to me why you did that? Thanks !!!

0 Votes 0 ·