C# 带补码运算符的编译器错误

C# 带补码运算符的编译器错误,c#,C#,我正在使用逻辑AND&=和补码~运算符,得到一个奇怪的编译器错误 // Constants private const byte XML_MATCH_ID = 0x01; private const byte XML_MATCH_MAC = 0x02; private const byte XML_MATCH_DEFAULT = (XML_MATCH_ID + XML_MATCH_MAC); // ... byte matchingTags = XML_MA

我正在使用逻辑AND
&=
和补码
~
运算符,得到一个奇怪的编译器错误

// Constants
private const byte XML_MATCH_ID         = 0x01;
private const byte XML_MATCH_MAC        = 0x02;
private const byte XML_MATCH_DEFAULT    = (XML_MATCH_ID + XML_MATCH_MAC);

// ...
byte matchingTags = XML_MATCH_DEFAULT;
// ... (reading XML nodes)

// Assume Machine ID doesn't match
matchingTags &= (byte)~XML_MATCH_ID;    // Compiler error: Constant value '-2' cannot be converted to a 'byte'

// Assume MAC Address doesn't match
matchingTags &= (byte)~XML_MATCH_MAC;   // Same compiler error but with "-3"
当我将上面的第一条语句更改为下面的等效语句时,一切都很好

matchingTags &= (0xff - XML_MATCH_ID);

为什么编译器会抛出此错误

编译器似乎试图将恭维词编译为常量。 我得到的编译器错误是“常量值计算溢出”

这并不奇怪<代码>字节是一个。(如果您正在查找,则应使用
sbyte

~XML\u MATCH\u ID
返回值为
-2
int
,该值不能强制转换为
字节(uint8)

解决此问题的一种方法是将
~XML\u MATCH\u ID
存储为临时
int
变量,然后执行逻辑和:

int temp = ~XML_MATCH_ID;  // temp now holds the value "-2"
byte temp2 = (byte)temp;   // temp2 now holds the value "254"
matchingTags &= temp2;
或者完全避免使用补码运算符:

matchingTags &= (byte.MaxValue - XML_MATCH_ID);

如果是c#,则使用unchecked关键字:错误消息显示“使用unchecked语法覆盖”。为什么不使用未检查的语法覆盖错误?对我来说,这个编译器警告是意外的
XML\u MATCH\u ID
是一个无符号8位整数,因此使用补码运算符对其所有位进行逆变换将产生另一个无符号8位整数。你建议在这里避免使用补码运算符是明智的。@AlainD:不幸的是,你的逻辑似是而非。C#没有运算符结果类型与其操作数类型相同的规则。相反,C#使用重载解析从许多内置运算符中进行选择,并且没有内置的取一个字节的求反运算符。在这种情况下,C#编译器将选择一个接受int的编译器,因此结果是int。@bendik:虽然这个答案是正确的,因为它产生了正确的结果,但执行错误消息已经告诉用户的操作会更加习惯,用户神秘地没有做到这一点:使用未检查的语法覆盖错误报告。@EricLippert:我不知道,所以谢谢。有了这些信息,编译器错误就不那么神秘了!在我看来,Bendiks关于在这种情况下避免使用补码运算符(以及
未选中的
)的建议更容易阅读,因此是更合适的选择。