为什么编译器不警告强制转换为枚举?
Why isn't the compiler warns about casting to enum?
当我意识到 D 允许用户将兼容值转换为 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
所以我的问题是:
这是否意味着,我,试图让事情变得安全(即处理)的库设计者,应该避免使用 final switch
,并使用其他方法(也许是常规 switch
和 default
情况)并在那里处理无效的 enum
状态(返回错误或抛出异常)?
为什么像D这样的现代安全语言允许我做这样的事情?也就是说,首先允许转换为 enum
的主要原因是什么? (从语言设计的角度来看。)
Note: I'm aware, that enum
can have a basetype, which can be string and in that case writeGreekLetter
doesn't really needed, however this is just a dummy example to demonstrate my main concern/problem.
在 D 中,强制转换是一种直接的低级操作:通过使用它们,程序员承认它们是在有意避免类型系统限制。 (这就是为什么转换语法使用特殊的 cast
关键字——通过提供可 greppable 的东西来帮助代码审查)。
要"safely"将整数转换为整型枚举,可以使用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)
当我意识到 D 允许用户将兼容值转换为 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
所以我的问题是:
这是否意味着,我,试图让事情变得安全(即处理)的库设计者,应该避免使用
final switch
,并使用其他方法(也许是常规switch
和default
情况)并在那里处理无效的enum
状态(返回错误或抛出异常)?为什么像D这样的现代安全语言允许我做这样的事情?也就是说,首先允许转换为
enum
的主要原因是什么? (从语言设计的角度来看。)
Note: I'm aware, that
enum
can have a basetype, which can be string and in that casewriteGreekLetter
doesn't really needed, however this is just a dummy example to demonstrate my main concern/problem.
在 D 中,强制转换是一种直接的低级操作:通过使用它们,程序员承认它们是在有意避免类型系统限制。 (这就是为什么转换语法使用特殊的 cast
关键字——通过提供可 greppable 的东西来帮助代码审查)。
要"safely"将整数转换为整型枚举,可以使用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)