【问题标题】:Using goto to fall-through in switch when also switching on type in C#在 C# 中同时打开类型时使用 goto 在 switch 中切换
【发布时间】:2021-11-06 02:20:44
【问题描述】:

编辑:我会重新提出问题: 是否有可能以这种方式使用 switch 语句。似乎一方面允许将类型作为案例来简化代码的外观,但是如果您想通过使用 go to 语句来实现重用,那么这是不可能的。就目前而言,我对语言结构更感兴趣,而不是实际解决我可以通过重复一些代码或转向 if else 语句来解决的问题。 我知道goto 通常很糟糕,但它似乎至少可以作为一种在 C 中模拟失败机制的方法是可以接受的,而不会因为使用/省略 break 而容易出错;误会了

我想在切换类型时使用switch 语句,但我想使用goto 来使用跌落谷

我想根据列表中元素的类型执行不同的操作: 但我收到错误:Use of unassigned local variable 'animal1' 我可以使用对象类型上的开关来执行此操作,还是需要比较字符串或使用 if-else 构造?

using System;
using System.Collections.Generic;
namespace switch_type_experiments
{
    public class Animal
    {
        public void Eat()
        { }
    }

    public class Mammal : Animal
    {
        public void DoMammalStuff()
        { }
    }

    public class Dog : Mammal
    {
        public void Bark()
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Animal> listOfAnimals = new();

            foreach (Animal animal in listOfAnimals)
            {
                switch (animal)
                {
                    case Dog animal1:

                        //do stuff only applicable for dog such as accessing 
                        // available only for dogs
                        animal1.Bark();
                        goto MammalLabel;

                    case Mammal animal1:
                    MammalLabel:
                        //do Mammal stuff
                        animal1.DoMammalStuff();
                        goto AnimalLabel;


                    case Animal animal1:
                    AnimalLabel:
                        animal1.Eat();
                        //do Animal stuff

                        break;
                    default:
                        break;
                }

            }
        }
    }
}

【问题讨论】:

  • 一般来说,使用goto 是一个的想法。你不应该这样做,除非你确切地知道你在做什么并且你必须使用它。您能否详细说明为什么您认为 goto 是解决您的问题的最佳解决方案? (在你的情况下,一系列if 可能是合适的。)
  • 不太确定是不是这样,但是您的错误使我相信您正在跳出animal1变量的范围。毕竟,当您来自 dog case 时,您在演员表之后跳跃(意味着您之前不执行这些东西),因此访问 animal1 会导致错误。
  • 我只想从一种情况切换到另一种情况以避免代码重复,因为我的对象和逻辑比示例复杂一些。这很可能比我把事情复杂化了。现在看来,我只需要摆脱animal1 并使用animal 并使用as 投射它。我认为我也误解了使用类型切换的工作原理。现在不确定这个问题有多大用处,如果它得到很多反对意见,我会删除它。

标签: c# switch-statement polymorphism goto


【解决方案1】:

如果我的理解是正确的,那么您可以只用 3 行代码而不是 switchgoto 语句来实现:

foreach (Animal animal in listOfAnimals)
{
    if (animal is Dog dog) dog.Bark();
    if (animal is Mammal mammal) mammal.DoMammalStuff();
    animal.Eat();
}

更新 #1:使用 switch 语句

在 C# 中,您可以调用 breakreturncontinuethrowgoto 来控制跌落。

goto 有一个非常特殊的版本,您可以在其中跳转到case x,而不是预定义的label x。但有一个警告:x 必须是编译时间常数。

因此,如果您坚持使用switch 语句,那么您可以执行以下操作之一:

int type = animal switch
{
    Dog dog => 3,
    Mammal mammal => 2,
    _ => 1
};

switch (type)
{
    case 3:
        (animal as Dog).Bark();
        goto case 2;
    case 2:
        (animal as Mammal).DoMammalStuff();
        goto case 1;
    case 1:
        animal.Eat();
        break;
}

ImmutableDictionary<Type, int> mapping = new Dictionary<Type, int>
{
    { typeof(Dog), 3 },
    { typeof(Mammal), 2 }
}.ToImmutableDictionary();

int type = mapping.TryGetValue(animal.GetType(), out type) ? type : 1;

switch (type)
{
    case 3:
        (animal as Dog).Bark();
        goto case 2;
    case 2:
        (animal as Mammal).DoMammalStuff();
        goto case 1;
    case 1:
        animal.Eat();
        break;
}

【讨论】:

  • 或者:(animal as Dog)?.Bark(); 应该也可以,而且更简洁一些
  • 是的,这可以使代码更加简洁。
  • 我知道这是一个很好的简洁解决方案,因此 +1,但现在我实际上更好奇 C# 中是否有类似的东西。我在问题中添加了一些细节
  • 让我考虑一下。
  • @PiotrGolacki 我已经扩展了我的答案,请检查一下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
相关资源
最近更新 更多