如何将代码结构化为 return 特定成员

How to structure the code to return certain members only

我想请问如何构造代码,以便当用户(主程序)指示没有苹果(hasApple = false)时,用户将无法访问fruitMenu.ApplefruitMenu.ApplePrice.

我想让程序在这样一种情况下运行:如果没有苹果,那么就不会有苹果和苹果的价格 属性 供用户 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();
        }
    }
}

一些问题的评论合并在一起可以用下面的代码表示。

我们应该让 Fruit 尽可能独立于它的实现 OrangeApple。由于他们没有额外的逻辑,我添加了字段 Type.

另外 Menu 不应该真正关心里面放的是什么。通过从中删除 HasAppleHasOrange,代码变得更易于维护——当我们想要引入新的水果类型时,我们唯一需要在代码中更改的就是为水果名称添加新类型.

如果未将水果添加到菜单中,则价格字段的访问受到限制,因为水果为 null

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();
        }
    }
}