替代使用if -else语句

时间:2015-04-25 05:29:08

标签: c# design-patterns

if --else if --block包含多个if语句的最佳替代方法是什么。

代码:

 string word="";

 if(letter=='a')
    {
       // do some action
       call(a);
    } 
 else if (letter=='b')
   {

           call(b)
   }

 else if (letter=='c')
   {
       call(c)
   }
 else if (letter=='d')
   {
       // do some action
       call(d)
   }
 else if (letter=='e')
   {
       // do some action
       call(e)
   }

    ................

     ..............

 else if (letter=='z')
   {
       // do some action
        call(z)
   }

如果有很多if-else语句,那么找到这种场景的解决方案的最佳方法是什么。有没有办法使用类/对象有效地设计这样的场景?

我相信我们很多人在设计/编码过程中会遇到这样的问题。是否有办法处理这种情况?

没有开关声明请。使用C#对象的有效设计算法将是最好的选择。

7 个答案:

答案 0 :(得分:6)

在C#中,最直接的翻译是switch语句。虽然switch严格来说不是面向对象的构造,但char也不是C#中的正确对象。

switch(letter)
{
    case 'a':
        call(a);
        break;

    case 'b':
        call(b);
        break;

    // and so on
}

如果参数不是简单的值类型而是对象,请使用虚方法而不是显式控制结构。这是真正的“面向对象”方式:在Smalltalk中,ifTrue:ifFalse:ifTrue:ifFalse:Boolean上的方法,将代码块作为参数!但是,C#使这个相当冗长。

static class Example {
    static void Sample(ISpeaker input) {
        input.Speak(); // this call acts like a control structure
    }
}

interface ISpeaker {
    void Speak();
}

class Cat : ISpeaker {
    public void Speak() {
        Console.WriteLine("Meow");
    }
}

class Dog : ISpeaker {
    public void Speak() {
        Console.WriteLine("Woof");
    }
}

如果你遇到一个简单的类型,另一种方法是明确的调度表

static readonly Dictionary<char, Action> dispatch
    = new Dictionary<char, Action> {
        { 'a', () => call(a) },
        { 'b', () => call(b) },
    };

static void Process(char letter) {
    dispatch[letter]();
}

如果您的条件对于基于Dictionary的调度表来说过于复杂,您可以使用基于List线性调度表,它更接近于其他行为-if chains:

static List<KeyValuePair<Func<char, bool>, Action>> dispatch
    = new List<KeyValuePair<Func<char, bool>, Action>>() {
        { x => x == 'a', () => call(a) },
        { x => x == 'b', () => call(b) },
        { x => true, () => callDefault() },
    };

static void Process(char letter) {
    dispatch.First(kvp => kvp.Key(letter)).Value();
}

答案 1 :(得分:2)

您可以执行以下操作:

private Dictionary<char, Action> _dic =
    new Dictionary<char, Action>
    {
        {'a', (Action)a},
        {'b', (Action)b},
        ...
    };

然后

var action = this._dic.TryGetValue(letter);
if (action == null)
{
    // this is like default case - no key matched the letter
}
else
{
    // call the action associated with the letter
    action();
}

答案 2 :(得分:1)

https://msdn.microsoft.com/en-us/library/06tc147t.aspx

你的意思是开关吗?这有效地像是一个很大的else-ifs

列表

答案 3 :(得分:1)

使用switch替代if...else

switch为您的代码提供了更多的可读性,并且更容易理解,如果在其他地方,如果您进行大量嵌套,则可能难以理解和阅读代码。

此外,与switch相比,if...else在性能方面略胜一筹。

希望这有帮助。

答案 4 :(得分:1)

从技术上讲,您选择了一种更复杂的方式来表达switch语句。切换语句,may be considered a "code smell"

如果我理解你的例子,你真的只想根据某个变量的值改变方法调用的参数。在将代码编写为switch语句时,可能没有任何好的方法可以改进,但是可能使用Dictionary来根据letter值查找参数是一个需要考虑的选项。

答案 5 :(得分:0)

您可以使用switch语句。

switch (letter)
{
    case 'a':
        case(a);
        break;
    case 'b':
        case(b);
        break;
    ...
    case 'z':
        case(z);
        break;
    default:
        Assert.Fail(letter.ToString() + " was an unexpected value");
        break;
}

答案 6 :(得分:-1)

使用switch语句:

switch(value)
{
     case value == "X":
          // handle
          break;
     case ...
           break;
    default:
           // Doesn't match any case above 
           break:
}