【问题标题】:Shorten long switch case缩短长开关盒
【发布时间】:2018-09-28 04:15:46
【问题描述】:

所以让我先说我是 C# 新手。我有一个 switch 语句,目前有 10 种不同的情况,但是,我需要使用它 3 次不同的时间(相同的 10 种情况,每种情况的结果不同),每种情况只有轻微的变化。

我觉得我只是在重复代码,有没有办法缩短它?

//Set the growth time of the crop based on what cropType.
        switch (cropType) {
            case 1:
                //Potatoes
                growth = 60;
                break;
            case 2:
                //Strawberries
                growth = 80;
                break;
            case 3:
                //Cabbages
                growth = 90;
                break;
            case 4:
                //Carrots
                growth = 40;
                break;
            case 5:
                //Melon
                growth = 120;
                break;
            case 6:
                //Pumpkin
                growth = 130;
                break;
            case 7:
                //Eggplant
                growth = 50;
                break;
            case 8:
                //Mushroom
                growth = 70;
                break;
            case 9:
                //Wheat
                growth = 40;
                break;
            case 10:
                //Truffle
                growth = 150;
                break;
        }

这是我的 1 部分代码。在第二部分中,我根据情况分配了一个图像,这必须单独完成,因为它依赖于增长和变化,而增长则不。我实际上并没有在其他开关上使用它。这是我在下面的另一个:

switch (cropType) {
            case 1:
                //Potatoes
                Debug.Log("Potatoes Harvested!");
                Global.potato += 2;
                break;
            case 2:
                //Strawberries
                Debug.Log("Strawberries Harvested!");
                Global.strawberry += 4;
                break;
            case 3:
                //Cabbages
                Debug.Log("Cabbages Harvested!");
                Global.cabbage += 1;
                break;
            case 4:
                //Carrots
                Debug.Log("Carrots Harvested!");
                Global.carrot += 3;
                break;
            case 5:
                //Melon
                Debug.Log("Melons Harvested!");
                Global.melon += 1;
                break;
            case 6:
                //Pumpkin
                Debug.Log("Pumpkins Harvested!");
                Global.pumpkin += 1;
                break;
            case 7:
                //Eggplant
                Debug.Log("Eggplant Harvested!");
                Global.eggplant += 2;
                break;
            case 8:
                //Mushroom
                Debug.Log("Mushrooms Harvested!");
                Global.mushroom += 4;
                break;
            case 9:
                //Wheat
                Debug.Log("Wheat Harvested!");
                Global.wheat += 6;
                break;
            case 10:
                //Truffle
                Debug.Log("Truffles Harvested!");
                Global.truffle += 1;
                break;
        }

基本上,它是一个脚本,需要根据其中的cropType 做不同的事情。

【问题讨论】:

  • 首先使用有意义的enum CropType { Potatoes = 1, Strawberries = 2, Cabbages = 3, ... } 而不是数字如何?然后将成长信息放入Dictionary<CropType, int> { { CropType.Potatoes, 60 }, { CropType.Strawberries, 80 }, ... },然后像var growth = growthDictionary[cropType];一样使用。
  • 如果你有一个多态的Crop 类型,你就不需要这样做了。您可以使用Growth 属性定义基本Crop 类,然后从中派生MushroomEggplant 之类的类型,并使用提供适当值的Growth 的重写实现。这意味着您还可以不必将数字映射到作物。
  • @spender - 是的,现在有了第二个例子,看起来 OP 可能想要一个 class Crop { public CropType Type { get; set; } public string Name { get; set; }, public int Growth { get; set; } public int ItemsPerHarvest { get; set; } [...] }
  • 这听起来像是您第二次更新后的xy problem。我认为您应该在此处发布有关您真正想要实现的目标的更多详细信息。最初听起来您想简化 switch,但现在听起来您遇到了类设计问题。
  • @spender 是的,我认为一个类肯定会在这里工作,因为我从其他类中获取了很多作物,而不仅仅是这个类。我可能不会仅仅因为我的时间有限,因为这是一项任务(我们的任务是“做点什么”),但如果我有时间,它会在我的名单上排名第一:)

标签: c# unity3d switch-statement


【解决方案1】:

就简化switch 语句而言,我认为Dictionary(如果键不是连续整数)、枚举或List(对于1-10 之类的东西,就像这里的情况一样)是合适的,创建数字之间的映射关系:

int[] growth = {0, 60, 80, 90, 40, 120, 130, 50, 70, 40, 150};
int cropType = 5; // for example
Console.WriteLine(growth[cropType]); // 120

这是一个字典示例,我认为它对人类来说更容易理解:

Dictionary<string, int> growth = new Dictionary<string, int>()
{
    {"Potatoes", 60}, 
    {"Strawberries", 80}, 
    {"Cabbages", 90}, 
    {"Carrots", 40}, 
    {"Melon", 120}, 
    {"Pumpkin", 130}, 
    {"Eggplant", 50}, 
    {"Mushroom", 70}, 
    {"Wheat", 70}, 
    {"Truffle", 150} 
};

Console.WriteLine(growth["Melon"]);

但是,在看到您的第二个 switch 声明后,您笨拙的 switches 似乎是更大设计问题的症状。您可以考虑添加一个Crop 类,该类具有您正在操作的所有属性的成员字段,例如typegrowth(以及描述Crop-ness 的任何其他属性或函数)。

Global 而言,您可以考虑聚合Crops 的第二个类,例如带有一个字典的Harvest 类,该字典记录每种作物的收获量。

长话短说,这些设计问题可能会变得非常模糊和基于意见,但希望这能提供一些前进的想法。

【讨论】:

  • 我可以将数字与单词联系起来,但在其他情况下我实际上并没有使用增长数字。
  • 我认为类“对人类来说更容易理解”,并且为可以使用类系统轻松表示的事物创建精细的映射系统是错误的。
  • @spender 我完全赞成上课,但引入一个班级系统只是为了替换switch 似乎是严重的矫枉过正。它最终可能是合适的,但我认为需要更多的上下文才能值得开销。 编辑: OP 添加了第二个开关,表明他们有设计问题,所以你现在可能有一点,他们需要 getter 和 setter。如果 OP 澄清这一点,我可以更新。
【解决方案2】:

也许这太多了,但您可以使用枚举和类/结构加上字典(如 ggorlen 建议的那样)

为什么要枚举?避免使用硬编码数字;不易出错并提高可读性;

private enum CropType
{
    Undefined = 0,
    Cabbages,
    Carrots,
    Eggplant,
    Melon,
    Mushroom,
    Potatoes,
    Pumpkin,
    Strawberries,
    Truffle,
    Wheat
}

private struct Crop
{
    public CropType Type { get; private set; }
    public float GrowthFactor { get; private set; }
    public float HarvestFactor { get; private set; }

    public Crop(CropType type, float growthFactor, float harvestFactor) 
    {
        this.Type = type;
        this.GrowthFactor = growthFactor;
        this.HarvestFactor = harvestFactor;
    }
}

private Dictionary<CropType, Crop> crops;
private Dictionary<CropType, Crop> Crops 
{
    get 
    {
        if (crops == null) 
        {
            crops = new Dictionary<CropType, Crop>() 
            {
                { CropType.Cabbages, new Crop(CropType.Cabbages, 90, 1) },
                { CropType.Carrots, new Crop(CropType.Carrots, 80, 5) }
                // here you can add the rest of your products...
            };
        }
        return crops;
    }
}

public Crop GetCrop(CropType crop) 
{
    if (!Crops.ContainsKey(type)) 
    {
        Debug.LogWarningFormat("GetCrop; CropType [{0}] not present in dictionary ", type);
        return null;
    }

    return Crops[type];
}

这是(最终)您将检索所需值的位置。

public float GetGrowthFactor(CropType type) 
{
    var crop = GetCrop(type);
    return crop == null ? default(float) : crop.GrowthFactor;
}

public float GetHarvestFactor(CropType type) 
{
    var crop = GetCrop(type);
    return crop == null ? default(float) : crop.HarvestFactor;
}

所以你会以这种方式要求值;

private void Example()
{
    var carrotsGrowth = GetGrowthFactor(CropType.Carrots);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    相关资源
    最近更新 更多