我使用枚举在类型系统中的类型之间切换,如:
enum FruitType {
APPLE;
PEAR;
CHERRY;
ORANGE;
BANANA;
.
.
.
}
现在我有几个函数只对子集有效(在函数之间有所不同),并且应该为所有其他函数抛出异常。
这可能是个人品味的问题,但您认为以下哪一项最容易阅读/可维护/最不容易出错?
或者是否有一个我想不到的更优雅的版本?
选项1:
switch(o.fruitType)
{
case APPLE:
case PEAR:
case ORANGE:
{
// do all the stuff i want to do
string ret;
// ...
function(o,ret);
return ret;
}
default:
throw InvalidFunctionParameterException();
}
选项2:
if(o.fruitType == APPLE || o.fruitType == PEAR || o.fruitType == ORANGE)
{
// do all the stuff i want to do
string ret;
// ...
function(o,ret);
return ret;
}
else
{
throw InvalidFunctionParameterException();
}
选项3:
switch(o.fruitType)
{
case APPLE:
case PEAR:
case ORANGE:
break;
default:
throw InvalidFunctionParameterException();
}
// do all the stuff i want to do
string ret;
// ...
function(o,ret);
return ret;
答案 0 :(得分:1)
编程风格。这是非常个人化的,每个人都有自己的看法。
我发现最好尝试做“什么表达我最好的意思”。换句话说,哪种写入方式代表了您期望的流程,以及您期望的行为,基于“这就是我想要发生的事情”(例如,需求规范告诉您代码应该是什么)做)。
我个人认为第三个最难读,因为它依赖于你发现throw
中间的switch
为关键。如果你在switch
(或if
)中放入其他“do stuff”功能,那么“我们为这些事情做这件事,其他任何事情都是错误的”就更清楚了。
我希望编译器最终会生成更多或更少的等效代码,可能会使switch
的代码略好于if
,因为switch
通常用表,if
或多或少必须遵循你所写的内容(条件短路是这里的一个重要特征)。
当然,您还必须考虑项目/公司编码样式指南,这可能有关于“如何编写switch语句”的说法。
答案 1 :(得分:1)
或者是否有一个我想不到的更优雅的版本?
将其实现为具有虚函数的类层次结构:
// client code:
o.processByFruitType();
class Fruit {
virtual string processByFruitType() {
throw InvalidFunctionParameterException();
}
};
// fruit implementations:
class Apple: public Fruit {
virtual string processByFruitType() override {
// do all the stuff i want to do
string ret;
// ...
function(*this,ret);
return ret;
}
};
其他专业化也遵循类似的实施方式。
答案 2 :(得分:1)
我同意,这是个人问题,但我相信,第一个选项是最具可读性的。
我也在情境中使用它,当函数应该对某些值做出反应时,明确地不应该对其他人做出反应:
switch(o.fruitType)
{
case APPLE:
{
DoSomethingWithApple();
break;
}
case PEAR:
{
DoSomethingWithPear();
break;
}
case ORANGE:
{
DoSomethingWithOrange();
break;
}
default:
{
// Explicitly left empty
}
}
我留下这个“Explicitly left empty
”评论,以便我的代码的未来读者知道,如果遇到其他值,我明确希望这段代码什么都不做。优化器会将此代码删除,因此不会影响性能。
答案 3 :(得分:-1)
或者是否有一个我想不到的更优雅的版本?
如果你在代码中执行了大量操作,那么编写支持这样的断言的函数/宏:
PARAM_ASSERT(o.fruitType == APPLE || o.fruitType == PEAR || o.fruitType == ORANGE);
// do all the stuff i want to do
string ret;
// ...
function(o,ret);
return ret;
实施可能含糊不清:
#define PARAM_ASSERT(X) \
do { \
if (!(X)) throw InvalidFunctionParameterException(); \
} while (false)
使用宏,您可以在不触及客户端代码的情况下保留使用__LINE__
,__FILE__
,#X
(条件的字符串化版本)等来丰富异常的自由。 ...