我正在涉及D,并且对具有指定基类型的命名vs匿名枚举的行为感到惊讶。给出以下D代码:
import std.stdio;
enum strs : string
{
Foo = "Hello",
Bar = "World",
}
enum : string
{
anon1 = "pen",
anon2 = "sword",
}
int main(string[] args)
{
writefln("%s %s", strs.Foo, strs.Bar);
writefln("%s %s", anon1, anon2);
return 0;
}
输出:
Foo Bar
pen sword
换句话说,对于命名的枚举,将值传递给writefln作为字符串会打印值的名称,而不是值本身。但对于匿名枚举,做同样的事情会打印出值本身。
这似乎是一种奇怪的不一致。那么为什么呢?
我使用的是Visual D 0.3.42。
答案 0 :(得分:3)
无名枚举只是一个清单常量块,并没有自己的类型。含义:
enum : string
{
anon1 = "pen",
anon2 = "sword",
}
...与...相同
enum string anon1 = "pen";
enum string anon2 = "sword";
但是,您的strs
枚举是一种类型,因此writefln
会打印出枚举字段名称(无论多么奇怪)。
答案 1 :(得分:3)
好吧,问题的一部分是关键字enum
在D中被过度使用。匿名枚举有时被称为清单常量。声明
enum : string
{
anon1 = "pen",
anon2 = "sword",
}
与
基本相同enum string anon1 = "pen";
enum string anon2 = "sword";
或
enum anon1 = "pen";
enum anon2 = "sword";
因为他们无论如何都会被推断为string
。这些真的不是枚举。只是你在块中而不是单独声明它们。他们更像是在C中定义一个常量,因为你声明了一个没有地址的符号,并且只会被替换为在使用该符号的地方分配的值。它不是enum
通常应该是的关联值列表。事实上,这些断言将会失败:
assert(is(typeof(anon1) == enum));
assert(is(typeof(anon2) == enum));
那是因为它们表现出传统意义上的常数而不是真正的枚举。与
对比assert(is(typeof(strs.Foo) == enum));
assert(is(typeof(strs.Bar) == enum));
会传递 - 因为strs
是一个实际的enum
而不是一个清单常量(虽然枚举类似于显式常量,因为它们没有地址,当你使用它们时,它们只会得到它们替换为它们的值 - 这可能是清单常量也使用enum
关键字的原因的一部分。)
因此,从writefln
的角度来看,anon1
和anon2
只是字符串,它会像任何字符串一样打印它们,而{{1 }和Foo
是枚举,因此它会打印出他们的名字。在内部,Bar
正在使用writefln
检查某些内容是否为is(T == enum)
,就像这些断言一样,只有实际枚举而不是显式常量才会导致该表达式为是的,所以他们是那些打印出他们名字的人。