Search code examples
c#member

How to structure the code to return certain members only


I would like to ask how can I structure the code so that when user (main program) indicates no apple (hasApple = false), user will not be able to access fruitMenu.Apple or fruitMenu.ApplePrice.

I wanna make the program to behave in a scenario that if there is not apple, then there won't be apple and price of apple property for user to select.

using System;

namespace ConsoleApplication
{
    public class Menu
    {
        public class Fruit
        {
            public string Apple { get; set; }
            public double ApplePrice { get; set; }
            public string Orange { get; set; }
            public double OrangePrice { get; set; }

            // Constructor
            public Fruit(string apple, double applePrice, string orange, double orangePrice)
            {
                this.Apple = apple;
                this.ApplePrice = applePrice;
                this.Orange = orange;
                this.OrangePrice = orangePrice;
            }
        }

        public bool HasApple { get; set; }
        public bool HasOrange { get; set; }

        public Fruit GetMenu()
        {
            string Apple;
            double ApplePrice;
            if (HasApple)
            {
                Apple = "Apple";
                ApplePrice = 5;
            }
            else
            {
                Apple = "No Apple";
                ApplePrice = double.NaN;
            }

            string Orange;
            double OrangePrice;
            if (HasOrange)
            {
                Orange = "Orange";
                OrangePrice = 5;
            }
            else
            {
                Orange = "No Orange";
                OrangePrice = double.NaN;
            }

            Fruit allFruits = new Fruit(Apple, ApplePrice, Orange, OrangePrice);
            return allFruits;
        }

        // Constructor
        public Menu(bool hasApple, bool hasOrange)
        {
            this.HasApple = hasApple;
            this.HasOrange = hasOrange;
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Menu menu = new Menu(true, false);            
            Menu.Fruit fruitMenu = menu.GetMenu();
            Console.Write(fruitMenu.Apple);
            Console.Write("\t");
            Console.WriteLine(fruitMenu.ApplePrice);
            Console.Write(fruitMenu.Orange);
            Console.Write("\t");
            Console.WriteLine(fruitMenu.OrangePrice);
            Console.ReadKey();
        }
    }
}

Solution

  • Some comments to question combined altogether can be represented by code below.

    We should make Fruit independent from its implementations Orange and Apple as much as possible. Since they don't have additional logic, I added field Type.

    Also Menu should not really care what is being put inside of it. By removing HasApple and HasOrange from it, code becomes more maintainable - when we want to introduce new type of fruit, the only thing we need to change in the code is just to add new type to fruit names.

    Access to price field is restricted by fruit being null in case it was not added to the menu

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace ConsoleApplication
    {
        public class FruitNames
        {
            public const string Apple = "Apple";
            public const string Orange = "Orange";
        }
    
        public class Fruit
        {
            public string Type { get; set; }
            public double Price { get; set; }
    
            public Fruit(string type, double price)
            {
                Type = type;
                Price = price;
            }
        }
        public class Menu
        {
            private List<Fruit> items = new List<Fruit>();
    
            public IEnumerable<Fruit> GetMenu()
            {
                return items;
            }
    
            public void Add(Fruit fruit)
            {
                items.Add(fruit);
            }
        }
    
        public static class MenuExtensions
        {
            public static Menu WithApple(this Menu menu)
            {
                menu.Add(new Fruit(FruitNames.Apple, 5));
    
                return menu;
            }
    
            public static Menu WithOrange(this Menu menu)
            {
                menu.Add(new Fruit(FruitNames.Orange, 10));
    
                return menu;
            }
            public static Fruit GetFruitOrDefault(this Menu menu, string type)
            {
                return menu.GetMenu().FirstOrDefault(x => x.Type == type);
            }
    
            public static Fruit GetAppleOrDefault(this Menu menu)
            {
                return menu.GetFruitOrDefault(FruitNames.Apple);
            }
    
            public static Fruit GetOrangeOrDefault(this Menu menu)
            {
                return menu.GetFruitOrDefault(FruitNames.Orange);
            }
        }
    
        public class Program
        {
            static void PrintFruit(Fruit fruit)
            {
                Console.Write(fruit.Type);
                Console.Write("\t");
                Console.WriteLine(fruit.Price);
            }
    
            static void Main(string[] args)
            {
                Menu menu = new Menu();
                Console.WriteLine("Menu without fruits:");
    
                Fruit apple = menu.GetAppleOrDefault();
                if (apple != null)
                {
                    PrintFruit(apple); // won't be printed
                }
    
                Fruit orange = menu.GetOrangeOrDefault();
                if (orange != null)
                {
                    PrintFruit(orange); // won't be printed
                }
    
                Console.WriteLine("Menu with fruits:");
                menu = menu.WithApple().WithOrange(); // fill menu with items
    
                apple = menu.GetAppleOrDefault();
                if (apple != null)
                {
                    PrintFruit(apple); // will be printed
                }
    
                orange = menu.GetOrangeOrDefault();
                if (orange != null)
                {
                    PrintFruit(orange); // will be printed
                }
    
                Console.ReadKey();
            }
        }
    }