我有一个基于枚举的方法,并且在开始时我们有这种情况:
public void MyMetohd(Somestatus status)
{
if(status == Somestatus.Enum1)
{
DoA();
DoB();
DoC();
DoD();
DoE();
}
if(status == Somestatus.Enum2)
{
DoA();
DoB();
DoC();
DoD();
}
if(status == Somestatus.Enum3)
{
DoA();
DoB();
DoC();
}
if(status == Somestatus.Enum4)
{
DoA();
DoB();
}
if(status == Somestatus.Enum5)
{
DoA();
}
}
你会如何优化这种代码(它不是我的代码)?
答案 0 :(得分:5)
如果您设置enum
的每个成员的值,则可以使用比较。
enum Somestatus : int
{
Enum1 = 1,
Enum2 = 2,
...
}
然后只需使用比较来完成代码。因为你总是DoA()
,所以从那开始。
if(status <= Somestatus.Enum5)
DoA();
if(status <= Somestatus.Enum4)
DoB();
if(status <= Somestatus.Enum4)
DoC();
...
继续这样做。这样,当值为Enum1
时,将调用所有函数。
答案 1 :(得分:5)
通过优化我会假设你的意思是“制造DRYer”。
你将不得不在易于阅读的代码(你拥有的代码,虽然略有重复性)和尽可能少重复的代码之间取得平衡
只要输入这个就会让我觉得很脏,但如果你想要的是DRY和更少的LOC,我认为它会做你想要的。
switch (status)
{
case Somestatus.Enum1:
DoE();
goto SomeStatus.Enum2;
case Somestatus.Enum2:
DoD();
goto SomeStatus.Enum3;
case Somestatus.Enum3:
DoC();
goto SomeStatus.Enum4;
case Somestatus.Enum4:
DoB();
goto SomeStatus.Enum5;
case Somestatus.Enum5:
DoA();
break;
default:
throw new InvalidArgumentException("Unknown Status");
}
答案 2 :(得分:3)
您可以在枚举值上使用字典键,并使用Action
或Action<T>
列表来执行。
Dictionary<int,IList<Action>> actionsPerEnumValue;
使用枚举值和每个字符的操作填充此字典。
在你的函数中获取每个值的函数列表并调用每个动作。
foreach(var act in actionsPerEnumValue[status])
{
act();
}
请参阅this SO答案以获取示例。
答案 3 :(得分:0)
乍一看,switch
语句似乎是最好的方法,但即使在那个方面你也有很多重复的代码:
switch (status)
{
case Somestatus.Enum1:
DoA();
DoB();
DoC();
DoD();
DoE();
break;
case Somestatus.Enum2:
DoA();
DoB();
DoC();
DoD();
break;
...
}
虽然这样做会更好,但仍然不理想,因为您重复调用了DoA
等。
答案 4 :(得分:0)
当你在相同的条件和不同的价值上工作时,当时更好的你使用switch..case ... 如果要测试多个条件,请使用If..else。
答案 5 :(得分:0)
你也可以“反转”逻辑,如果它更简单(取决于要覆盖的枚举数量与不同行动的数量):
if(status == Somestatus.Enum1 || status == Somestatus.Enum2)
DoA();
if(status == Somestatus.Enum1 || status == Somestatus.Enum4)
DoB();
...
答案 6 :(得分:0)
听起来应该使用State Pattern
答案 7 :(得分:0)
<强>编辑:强>
// ANOTHER WAY
public void MyMetohd(Somestatus status)
{
switch(status)
{
case Somestatus.Enum1:
do_("ABCDE");
break;
case Somestatus.Enum2:
do_("ABCD");
// and so on...
}
}
public static void do_(string s)
{
foreach(char ch in s)
{
switch(ch)
{
case 'A':
doA();
break;
case 'B':
doB();
break;
case 'C':
doC();
break;
case 'D':
doD();
break;
case 'E':
doE();
break
}
}
}
答案 8 :(得分:0)
使用模式来解决这个问题将是其他人建议的最佳解决方案。我想提供另一种解决方案。
我强烈建议不要这样做。
public void MyMetohd(Somestatus status)
DoA();
if (status != SomeStatus.Enum5) {
DoB();
if (status != SomeStatus.Enum4) {
DoC();
if (status != SomeStatus.Enum3) {
DoD();
if (status != SomeStatus.Enum2) {
DoE();
}
}
}
}
}
答案 9 :(得分:0)
虽然我自己会选择Brook的解决方案,但我想指出另一个优雅而简短的解决方案。
public void MyMethod(Somestatus status)
{
foreach (Action toDo in new Action[] { DoA, DoB, DoC, DoD, DoE }.Take(5 - (int)status))
toDo();
}
但是,这假定Somestatus的定义如下:
enum Somestatus
{
Enum1,
Enum2,
Enum3,
Enum4,
Enum5
}
我喜欢这个解决方案作为一个学者,因为它很短,但它肯定没有很好的可读性或可维护性。