干掉switch语句
goto,可以说是程序界,名声最差的关键字之一了。有人强烈要求,在高级语言中,应该被和谐掉。
如果,你在满是高级业务逻辑的代码里,写上些goto,就好比,你在代码里,嵌了些汇编语言(goto应该待它自己的世界).
其实,我们常用的switch语句中,goto也若隐若现。请参考MSDN关于switch的说明文档。
现在,我分析一下,我们为啥要用switch语句:
先从一个简单的例子入手:
[Test(Description="switch可以被if等价代替")] public void T1() { int x = 6; //if语句 if (x % 2 == 0) { Console.WriteLine("偶数"); } else if (x % 2 == 1) { Console.WriteLine("奇数"); } else { Console.WriteLine("未知数"); } //等价的switch语句 switch (x % 2) { case 0: Console.WriteLine("偶数"); break; case 1: Console.WriteLine("奇数"); break; default: Console.WriteLine("未知数"); break; } }
可以看出,if与switch几乎没啥区别,纯属个人爱好!
再举个例子:
[Test(Description="可能用到switch的地方")] public void T2() { int x = 6; //if语句分支太多! if (x == 0) { Console.WriteLine("x=0"); } else if (x == 1 || x == 2 || x == 3 || x == 4) { Console.WriteLine("0<x<5"); } else if (x == 5) { Console.WriteLine("x=5"); } else if (x == 6 || x == 7 || x == 8 || x == 9) { Console.WriteLine("5<x<10"); } else { Console.WriteLine("x<0 or x>9"); } //用switch语句更清晰? switch (x) { case 0: Console.WriteLine("x=0"); break; case 1: case 2: case 3: case 4: Console.WriteLine("0<x<5"); break; case 5: Console.WriteLine("x=5"); break; case 6: case 7: case 8: case 9: Console.WriteLine("5<x<10"); break; default: Console.WriteLine("x<0 or x>9"); break; } }
可以看出,遇到这种情况,switch看起来还不错!
现在,我想用用switch的"高级"功能:
[Test(Description="可以作为糟糕的笔试题")] public void T3() { int x = 6; switch (x) { case 0: Console.WriteLine("x=0"); goto case 0;//while(true)!!! case 1: case 2: case 3: case 4: Console.WriteLine("0<x<5"); goto default; case 5: Console.WriteLine("x=5"); break; case 6: case 7: case 8: case 9: Console.WriteLine("5<x<10"); goto case 1; default: Console.WriteLine("x<0 or x>9"); break; } }
你可以在30"之内,"算"出结果吗?
我真正想说的是,除了if...else...与switch外,我们仍然有选择的余地:
[Test(Description="干掉switch语句")] public void T4() { //我用Dictionary来组织这些规则,可以自定义更高级的类 var rules = new Dictionary<Predicate<int>, Action> { {x => x==0, ()=>Console.WriteLine("x=0")}, {x => 0<x&&x<5, ()=>Console.WriteLine("0<x<5")}, {x => x==5, ()=>Console.WriteLine("x=5")}, {x => 5<x&&x<10, ()=>Console.WriteLine("5<x<10")}, {x => x<0&&9<x, ()=>Console.WriteLine("x<0 or x>9")}, {x => true, ()=>Console.WriteLine("默认")} }; int y = 6; //找出所有满足要求的规则 rules.Where(x => x.Key(y)).each(x => x.Value()); //只找出一条满足要求的规则 rules.First(x => x.Key(y)).Value(); }
用Predicate/Action就解决了问题,感觉还好吗?


