有没有办法简化这个switch-case?

Is there a way to simplify this switch-case?

如标​​题所说,我想简化一个switch-case语句。我目前在我的 switch-case 声明中有这个:

switch(someEnum) {
case EnumType.A:
    SomeMethodSpecificToA();
    AMethodIShouldCallOnAllVowels();
    break;
case EnumType.B:
case EnumType.C:
case EnumType.D:
    SomeMethodSpecificToTheseThreeLetters();
    AMethodIShouldCallOnAllConsonants();
    break;
case EnumType.E:
    SomeMethodSpecificToE();
    AMethodIShouldCallOnAllVowels();
    break;
// All other letters, also containing the vowels & consonants methods
}

所以我知道我可以链接多个 case 语句让它们做同样的事情,但我不知道我怎样才能做到让 2 个字母做 2 个独立的事情然后落入第二个陈述,针对所有元音(或所有辅音)。在 Swift 我会做这样的事情:

func test(someEnum: EnumType) {
    switch someEnum {
    case .A:
        someMethodSpecificToA()
        fallthrough
    case .B, .C, .D:
        someMethodSpecificToTheseThreeLetters()
        fallthrough
    case .E:
        someMethodSpecificToE()
        fallthrough
    case .A, .E:
        aMethodIShouldCallOnVowels()
    case .B, .C, .D:
        aMethodIShouldCallOnAllConsonants()
    }
}

有没有不使用 2 个 switch 语句就可以做到这一点的方法?这似乎是多余的,因为我已经打开了那个变量。

进入下一个案例是"goto Case 2;"。 我也相信这是一个相关的问题: [Using `continue` keywoard in a switch nest inside a foreach loop

当我必须了解执行 case A 时会发生什么时,我不想向下滚动整个开关以查明 A 是否不止一次出现。

在重构之后,您真的得到了一个更好维护的程序吗? KISS 解决方案难道不是仅在 A 标签后分组 'all stuff for A' 吗?

我会简单地将 cases 限制为 Specific()'s,并在 switch block 之后放置一个简单的 if-else:

if IsVowel
    AMethodIShouldCallOnAllVowels();
else
    AMethodIShouldCallOnAllConsonants();

另请查看 default:(但在这种情况下可能没有用)。

Is there a way to do this without using 2 switch statements?

是的。使用 if 语句。

EnumType[] Vowels = new [] {EnumType.A, EnumType.E, EnumType.I, EnumType.O, EnumType.U};

if (someEnum == EnumType.A)
    SomeMethodSpecificToA();

if (new [] {EnumType.B, EnumType.C, EnumType.D}.Contains(someEnum))
    SomeMethodSpecificToTheseThreeLetters();

if (someEnum == EnumType.E)
    SomeMethodSpecificToE();

if (Vowels.Contains(someEnum))
    AMethodIShouldCallOnAllVowels();

根据实际代码中 'letters' 的复杂性,您可能会发现 类 比枚举更适合。这样做,您可以替换所有条件逻辑(if 和 switch 语句)。一种重构选项可能如下所示:

abstract class Letter
{
    public char Value { get; private set; }
    protected abstract void FrobInternal();
    public void Frob()
    {
        FrobInternal();
        // optionally code to be called for all letters
    }

    // private constructor limits inheritance to nested classes
    private Letter(char value) { Value = value; }

    class Vowel : Letter
    {
        public Vowel(char letter) : base(letter) { }
        sealed protected override void FrobInternal()
        {
            FrobVowel();
            AMethodIShouldCallOnAllVowels();
        }
        protected virtual void FrobVowel() { }
        private void AMethodIShouldCallOnAllVowels()
        {
            // Implementation...
        }
    }
    class Consonant : Letter
    {
        public Consonant(char letter) : base(letter) { }
        sealed protected override void FrobInternal()
        {
            FrobConsonant();
            AMethodIShouldCallOnAllConsanants();
        }
        protected virtual void FrobConsonant() { }
        private void AMethodIShouldCallOnAllConsanants()
        {
            // Implementation...
        }
    }

    class ConsonantBCD : Consonant
    {
        public ConsonantBCD(char letter) : base(letter) { }
        protected override void FrobConsonant()
        {
            // Special implemenation for B, C, D
        }
    }

    class LetterA : Vowel
    {
        public LetterA() : base('A') { }
        protected override void FrobVowel()
        {
            // Special implementation for A
        }
    }
    class LetterE : Vowel
    {
        public LetterE() : base('E') { }
        protected override void FrobVowel()
        {
            // Special implementation for E
        }
    }

    // use public readonly fields to replicate Enum functionality
    public static readonly Letter A = new LetterA();
    public static readonly Letter B = new ConsonantBCD('B');
    public static readonly Letter C = new ConsonantBCD('C');
    public static readonly Letter D = new ConsonantBCD('D');
    public static readonly Letter E = new LetterE();
    public static readonly Letter F = new Consonant('F');
    // ...   
    public static readonly Letter Z = new Consonant('Z');
}

然后您可以将上面的原型函数简单地替换为:

void Test(Letter l) {
    l.Frob();
}

上述重构只是一组封闭值模拟枚举的一个选项。策略或访问者模式也可能有助于考虑。