我偶然发现在枚举定义中使用了加号(+)运算符,我很惊讶地看到随附的测试通过了。任何人都知道这可以记录在哪里?
public enum ApprovalItemState
{
Enqueued = 1,
Approved = 2,
Denied = 4,
Acknowledged = 8,
ApprovalAcknowledged = ApprovalItemState.Approved + ApprovalItemState.Acknowledged,
DenialAcknowledged = ApprovalItemState.Denied + ApprovalItemState.Acknowledged
}
[TestClass]
public class ApprovalItemStateTests
{
[TestMethod]
public void AreFlagsDeniedAndAcknowledged()
{
Assert.AreEqual(ApprovalItemState.DenialAcknowledged, ApprovalItemState.Denied | ApprovalItemState.Acknowledged);
}
[TestMethod]
public void IsDenialAcknowledged()
{
Assert.IsTrue(Enum.IsDefined(typeof(ApprovalItemState), ApprovalItemState.Denied | ApprovalItemState.Acknowledged));
Assert.AreEqual(ApprovalItemState.Denied | ApprovalItemState.Acknowledged, (ApprovalItemState)Enum.Parse(typeof(ApprovalItemState), "DenialAcknowledged"));
}
[TestMethod]
public void IsNotDeniedAndApproved()
{
Assert.IsFalse(Enum.IsDefined(typeof(ApprovalItemState), ApprovalItemState.Approved | ApprovalItemState.Denied));
}
}
答案 0 :(得分:11)
里德的答案当然是正确的。我只是觉得我会添加一些有趣的琐事。首先,当你在里面枚举时,枚举的所有成员都在范围内。这是C#中唯一可以通过其非限定名称使用枚举成员的情况!
public enum ApprovalItemState
{
Enqueued = 1,
Approved = 2,
Denied = 4,
Acknowledged = 8,
ApprovalAcknowledged = Approved | Acknowledged,
DenialAcknowledged = Denied | Acknowledged
}
第二个琐事是C#编译器实际上允许enum算术涉及枚举中的其他枚举!
enum E
{
E1
}
enum F
{
F1
}
enum G
{
G1 = E.E1 + F.F1
}
通常情况下,这根本不合法;你不能在一起添加两个不同的枚举,你不能分配结果。编译器在枚举初始值设定项中放宽这些规则,以便您可以执行以下操作:
enum MyFlags
{
MyReadOnly = FileFlags.ReadOnly,
...
答案 1 :(得分:10)
14.5中的C#语言规范声明:
以下运算符可用于枚举类型的值:==,!=,<,>,< =,> =(§7.10.5),二进制+(§7.8.4),二进制 - (§7.8.5),^,&,| (§7.11.2),〜(§7.7.4),++和 - (§7.6.9和§7.7.5)。
基本上,由于枚举在内部存储为Int32
(这是默认值,除非您指定不同的存储类型),您可以像这样添加。
但是,使用|
代替+
来定义蒙版更为常见。此外,如果您要将此作为标志枚举使用,则通常会包含[Flags]
。
答案 2 :(得分:2)
...每个枚举类型都有一个底层类型,除了char之外,它可以是任何整数类型。 枚举元素的默认基础类型是int ...
顺便说一下,使用|
代替+
来组合枚举标志值更具惯用性(并且更不容易出错)。例如,这个错误不会导致问题:
DenialAcknowledged =
ApprovalItemState.Denied
| ApprovalItemState.Acknowledged
| ApprovalItemState.Denied
但是这个错误会导致问题:
DenialAcknowledged =
ApprovalItemState.Denied
+ ApprovalItemState.Acknowledged
+ ApprovalItemState.Denied
答案 3 :(得分:1)
Approved + Acknowledged
只是一个常量,因此可以将其指定为枚举元素的值。
关于测试 - 它们起作用因为int值是“快乐的”,所以(a + b) == (a | b)
但是如果你改变了那样的话:
public enum ApprovalItemState
{
Enqueued = 1,
Approved = 2,
Denied = 7,
Acknowledged = 18,
ApprovalAcknowledged = Approved + Acknowledged,
DenialAcknowledged = Denied + Acknowledged
}
并且测试不会通过。
答案 4 :(得分:0)
这并不奇怪 - 枚举用整数类型表示。你也可以使用其他运算符,虽然如果你打算使用标志(这个例子正在做),最好使用[Flags]属性来定义它们,并且更好地更清楚地布局:
[Flags]
public enum ApprovalItemState
{
Enqueued = 1 << 0,
Approved = 1 << 1,
Denied = 1 << 2,
Acknowledged = 1 << 3,
ApprovalAcknowledged = ApprovalItemState.Approved | ApprovalItemState.Acknowledged,
DenialAcknowledged = ApprovalItemState.Denied | ApprovalItemState.Acknowledged
}
答案 5 :(得分:0)
我会为你分解其中一个。
DenialAcknowledged = ApprovalItemState.Denied + ApprovalItemState.Acknowledged
DenialAcknowledged = 4 + 8
DenialAcknowledged = 12
对于此测试:
[TestMethod]
public void AreFlagsDeniedAndAcknowledged()
{
Assert.AreEqual(ApprovalItemState.DenialAcknowledged, ApprovalItemState.Denied | ApprovalItemState.Acknowledged);
}
您正在检查:
ApprovalItemState.DenialAcknowledged == ApprovalItemState.Denied | ApprovalItemState.Acknowledged
12 == 4 | 8
12 == 0100 | 1000 //bitwise operation
12 == 1100
12 == 12 //convert from binary to decimal
这就是测试通过的原因。通过查看代码并不简单。