当我意识到D允许用户将兼容值转换为int main() {
DT1<double> d1;
DT1<int> d2;
DT2<double> d3;
DT1<double> dupeType;
doit(d3); // calls foo2()
}
时,我感到非常震惊,因此可以生成无效的enum
值,我认为这是有问题的很多层次。
例如,如果我创建了一个库,我在其中公开enum
类型和正在处理它的函数:
enum
...然后用户执行以下操作:
module greek;
import std.stdio : writeln;
enum GreekLetters
{
ALPHA,
BETA,
}
void writeGreekLetter(GreekLetters letter)
{
final switch(letter)
{
case GreekLetters.ALPHA:
writeln("\u03B1");
break;
case GreekLetters.BETA:
writeln("\u03B2");
break;
}
}
...编译器不会抱怨,但显然程序会崩溃(不太好)异常:
import greek : GreekLetters, writeGreekLetter;
void main()
{
writeGreekLetter(cast(GreekLetters)2);
}
所以我的问题是:
这是否意味着,我,试图安全(即处理)的图书馆设计师应避免使用core.exception.SwitchError@greek(14): No appropriate switch clause found
,并使用其他方法(可能是常规的{{1带有final switch
的情况)并在那里处理无效的switch
状态(返回错误或抛出异常)?
为什么像D这样的现代安全语言允许我做这样的事情?也就是说,首先允许default
的主要原因是什么? (从语言设计的角度来看。)
注意:我知道,
enum
可以有一个基本类型,可以是字符串,在这种情况下enum
并不是真的需要,但这只是一个虚拟的例子来证明我的主要关注/问题。
答案 0 :(得分:6)
在D中,强制转换是一种钝的低级操作:通过使用它们,程序员承认他们故意避免类型系统限制。 (这就是为什么转换语法使用特殊的cast
关键字 - 通过提供一些可以提供的东西来帮助代码审查。)
安全地&#34;将整数转换为整数枚举,您可以使用std.conv.to
。例如:
writeGreekLetter(2.to!GreekLetters);
此代码仍将编译,但会在运行时提供更好的错误消息:
Value (2) does not match any member value of enum 'GreekLetters'
要在编译时检查整数文字的转换,可以先使用CTFE将其分配给manifest constant:
enum greekLetter2 = 2.to!GreekLetters;
writeGreekLetter(greekLetter2);
这段代码将无法正确编译:
Error: uncaught CTFE exception std.conv.ConvException("Value (2) does not match any member value of enum 'GreekLetters'"c)