C# · 12月 30, 2021

c# – “?”type modifer precedence vs logical and operator(&)vs address-of operator(&)

更新:
看来我并不清楚我正在问的是什么(随着时间的推移,我也失去了一点),所以这里是一个tl; dr版本: var test1 = a is byte & b; // compilesvar test2 = a is byte? & b; // does not compilevar test3 = a is byte? && b; // compiles

这意味着 – 据我所知 – 那个?类型修饰符具有较低的优先级(因为它不是运算符,这可能不是最好的词)比&运算符,但高于&&&操作符.是这样吗?标准中描述的是哪里?

和原来的问题:

在尝试从Jon Skeet的优秀博客A Tale of two puzzles中找出第二个难题的答案时,我遇到了一个问题:

unsafe private void Test<T>(T a,bool b) { var test1 = a is byte? & b; // does not compile var test2 = a is byte? && b; // compiles var test3 = a is byte ? & b : & b; // compiles}

在这里,我使用不安全的上下文,因为我的实际目标需要它(例如:第三行),但是没有必要再现我提出的问题. (但是它可能会产生效果,因为它会引入运算符的地址作为&符号的替代方法.)

第一行不编译(其他的),它给出以下错误消息:

Syntax error,’:’ expected

这意味着在这种情况下,编译器将该行视为

var test1 = (a is byte) ? &b [: missing part that it complains about];

在第二行,它将其视为:

var test2 = (a is byte?) && (b);

我检查了运算符优先级(here),顺序(从最高到最低)如下:&&&&?:,所以这一点不解释为什么第一行在第二行没有编译时或至少不适合我 – 也许这是我错了…)编辑:我明白为什么第二个编译,所以请不要专注于这个在你的答案.

我的下一个预感是,不管怎样,优先级(如果有这样的事情)?类型修饰符位于这两个(或实际上是三个)运算符之间的位置(&和&&).可以这样吗如果没有人能解释我遇到的确切行为?评估顺序是?类型修饰符在标准中的某个地方清晰描述?

编辑:我也知道有一个一元地址的操作符(实际上这是我试图用于解决方案的诀窍…),这在这里起了一个作用,但我的问题仍然保持不变.

在同样的不安全的上下文中,可以快乐地编译:

var test1 = true & b;var test2 = true && b;// orvar test1 = a is byte & b;var test2 = a is byte && b;

所以我认为它必须是相关的?修饰符/运算符,而不仅仅是运算符优先的地址(否则两个test1行将不会编译).

P.S .:我知道我可以在我的代码中加上括号,所以它会编译,但我想避免:

var test = (a is byte?) & b; // compiles

更新:
我曾经尝试过Roslyn,我认为附加AST可能是一个好主意:

var test1 = a is byte & b; var test2 = a is byte? & b; var test3 = a is byte? && b;

我想强调,我不是在链接的文章中寻找解决原始问题的解决方案(当然我正在寻找一个,但是我请你不要在这里给出答案,因为我想找到我自己的.)
另外,如果我在找到解决方案的错误轨道上,请不要评论,我只提到了一些难题,为我的具体问题提供一些上下文,并提供了一个很好的借口来编写这样的代码.

解决方法 这里的线索是不安全的关键字.实际上有两个不同的运算符 – 按位和AND操作符你习惯了,而且地址 – &操作符不仅具有较高的优先级,而且是 evaluated right-to-left,像所有一元操作符一样.

这意味着首先评估& b,并产生指针值.声明的其余部分,正如编译器所抱怨的那样,是不可粗略的. (a是字节?)(地址),或(正如编译器尝试解析它)(a是字节)? (地址),并且缺少:.

替换& amp;与或 –,两个符号可以是一元或二进制运算符.

第二份声明的准确理由是,没有一个一元的,从右到左的高优先级&操作符.