Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 0到枚举的隐式转换_C#_Enums_Type Conversion_Implicit Conversion - Fatal编程技术网

C# 0到枚举的隐式转换

C# 0到枚举的隐式转换,c#,enums,type-conversion,implicit-conversion,C#,Enums,Type Conversion,Implicit Conversion,在C#中,十进制文本0可以隐式转换为枚举(或基础类型为枚举的可空值) ,GitHub上的当前版本 隐式枚举转换 允许将十进制整数文字0转换为任何枚举类型 以及任何基础类型为枚举类型的可为空的类型。在 后一种情况下,通过转换为 基础枚举类型并包装结果(可为null的类型) ,第11.2.4节隐式枚举转换 隐式枚举转换允许十进制整数文字 0(或0L等)转换为任何枚举类型和任何 其基础类型为枚举类型的可空值类型。在 后一种情况下,通过转换为 基础枚举类型和包装结果(§9.3.11) 基于此,以下所有例

在C#中,十进制文本
0
可以隐式转换为枚举(或基础类型为枚举的可空值)

,GitHub上的当前版本

隐式枚举转换 允许将十进制整数文字0转换为任何枚举类型 以及任何基础类型为枚举类型的可为空的类型。在 后一种情况下,通过转换为 基础枚举类型并包装结果(可为null的类型)

,第11.2.4节隐式枚举转换

隐式枚举转换允许十进制整数文字 0(或0L等)转换为任何枚举类型和任何 其基础类型为枚举类型的可空值类型。在 后一种情况下,通过转换为 基础枚举类型和包装结果(§9.3.11)

基于此,以下所有例子都应该是合法的。这个例子来自Eric Lippert的文章

然而,正如Eric所解释的,以下案例应该是非法的:

E e6 = 0 | 0 | E.X;
原因是
0 | 0 | E.X
(0 | 0)| E.X
相同,
0 | 0
不是一个文本,而是一个值为0的编译时常量。以下情况也是如此:

E e7 = 1 - 1;
E e8 = 2 - 1 - 1 + 0;
E e9 = (0L & 1);
但是,这些都很好<在本例中,code>e6、
e7
e8
e9
的值为
E.X


为什么呢?标准中是否有一个(较新的)规范规定编译时常数0也可以隐式转换为任何枚举,或者这是编译器在不严格遵循规范的情况下所做的吗?

正如您所指出的,
0 | 0 | E.X
被绑定为
(0 | 0)| E.X

Eric注意到编译器没有遵循
0 | 0 | E.X
的规范:

在得到一个完整的解析树之后,我们将遍历解析树,确保所有类型都能正常工作。不幸的是,初始类型绑定传递的算术优化非常奇怪。它检测到0 |某物并积极地用某物替换它,因此就编译器而言,第六种情况与第二种情况相同,这是合法的。啊

Eric在评论中指出:

但是(7-7)| E.X确实会产生错误

Roslyn在折叠常量方面似乎比本机编译器聪明一点。很可能他们的目标是提高效率,而不关心在边缘案例中为bug行为保留bug

出于同样的原因,同样的问题现在似乎适用于
7-7
,或者编译器在初始类型绑定过程中可以计算为
0
的任何其他表达式

我认为不断的折叠正在发生:

如您所见,这将创建一个新的
ConstantValue
。所以
(0 | 0)| E.X
被折叠到
0 | E.X
,其中第一个
0
是一个常数。当编译器开始折叠
0 | E.X
时,它不知道
0
在原始源代码中不是文本
0
,而是编译器生成的常量,因此将其折叠,就像您最初编写了
0 | E.X
一样


与您的其他示例完全相同,我认为这是由相同的代码完成的
1-1
和其他代码一样,被折叠成一个常量
0
。编译器在编译时可以计算为
0
的任何表达式都会发生这种情况。

自2006年以来,情况可能发生了变化。它在哪个版本的C#中工作,在哪个版本中不工作?我认为这在所有方面都是一样的。与.NET framework 4.6.2和.NET core 2.1配合使用。@MariusBancila您需要非常谨慎地使用这里的语言。。。这是一个编译器的东西-“.NETFramework4.6.2和.NETCore2.1”都是运行时-坦率地说,它们甚至没有投票权。这里重要的是编译器版本。当然,你说得对。从ISO-2到C#7.3,我什么都试过了。它们都是一样的。
E e7 = 1 - 1;
E e8 = 2 - 1 - 1 + 0;
E e9 = (0L & 1);
newValue = FoldNeverOverflowBinaryOperators(kind, valueLeft, valueRight);
if (newValue != null)
{
    return ConstantValue.Create(newValue, resultType);
}