gpt4 book ai didi

c# - 为什么在另一个枚举声明中允许不同枚举类型之间的操作,而在其他地方不允许?

转载 作者:IT王子 更新时间:2023-10-29 04:34:48 24 4
gpt4 key购买 nike

C# 编译器允许在另一个枚举类型声明中的不同枚举类型之间进行操作,如下所示:

public enum VerticalAnchors
{
Top=1,
Mid=2,
Bot=4
}

public enum HorizontalAnchors
{
Lef=8,
Mid=16,
Rig=32
}

public enum VisualAnchors
{
TopLef = VerticalAnchors.Top | HorizontalAnchors.Lef,
TopMid = VerticalAnchors.Top | HorizontalAnchors.Mid,
TopRig = VerticalAnchors.Top | HorizontalAnchors.Rig,
MidLef = VerticalAnchors.Mid | HorizontalAnchors.Lef,
MidMid = VerticalAnchors.Mid | HorizontalAnchors.Mid,
MidRig = VerticalAnchors.Mid | HorizontalAnchors.Rig,
BotLef = VerticalAnchors.Bot | HorizontalAnchors.Lef,
BotMid = VerticalAnchors.Bot | HorizontalAnchors.Mid,
BotRig = VerticalAnchors.Bot | HorizontalAnchors.Rig
}

但在方法代码中禁止它们,即操作:

VerticalAnchors.Top | HorizontalAnchors.Lef;

被标记为此错误:

Operator '|' cannot be applied to operands of type 'VerticalAnchors' and 'HorizontalAnchors'.

当然有一个解决方法:

(int)VerticalAnchors.Top | (int)HorizontalAnchors.Lef

我对这种编译器行为很好奇。为什么在另一个枚举声明中允许不同枚举类型之间的操作,但在其他地方不允许?

最佳答案

既然你没有在你的问题中提出问题,我会假装你问了一些有趣的问题并回答它们:

Is it true that inside an enum declaration, you can use values of other enums in the initializers?

是的。你可以说

enum Fruit { Apple }
enum Animal { Giraffe = Fruit.Apple }

尽管将 Fruit.Apple 赋值给 Animal 类型的变量而不进行强制转换是不合法的。

这个事实有时令人惊讶。事实上,我自己也很惊讶。当我第一次尝试这样做时,为了测试编译器的一部分,我认为这可能是一个错误。

Where in the spec does it say that is legal?

第 14.3 节说初始化器必须是常量,并且常量将被转换为枚举的基础类型。枚举成员是常量。

Ah, but what about this case?

enum Fruit { Apple = 1 }
enum Shape { Square = 2 }
enum Animal { Giraffe = Fruit.Apple | Shape.Square }

That expression isn't a legal constant expression in the first place, so what's up?

好的,你让我到那里。 14.3 节也确实说初始化器中使用的枚举成员不需要转换,但不清楚它是指正在初始化的枚举的成员还是任何枚举 。两者都是一种合理的解释,但没有具体的语言,很容易认为前者的意思就是本意。

因此这是一个已知缺陷;几年前我向 Mads 指出了这个问题,但它从未得到解决。一方面,规范没有明确允许。另一方面,该行为既有用又符合规范的精神(如果不完全符合规范的文字)。

基本上,实现所做的是在处理枚举初始值设定项时,将所有枚举成员视为其基础类型的常量表达式。 (当然,它确实需要确保枚举定义是非循环的,但这也许最好留给另一个问题。)因此它不会“看到”FruitShape 没有定义“或”运算符。

虽然不幸的是规范措辞不清楚,但这是一个理想的功能。事实上,我在 Roslyn 团队中经常使用它:

[Flags] enum UnaryOperatorKind { 
Integer = 0x0001,
...
UnaryMinus = 0x0100,
...
IntegerMinus = Integer | UnaryMinus
... }

[Flags] enum BinaryOperatorKind {
...
IntegerAddition = UnaryOperatorKind.Integer | Addition
... }

能够混合匹配从各种枚举中获取的标志非常方便。

关于c# - 为什么在另一个枚举声明中允许不同枚举类型之间的操作,而在其他地方不允许?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14541668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com