C#字节类型和文字

C#字节类型和文字,c#,C#,下面的代码可以工作 byte b = 1; 但是我注意到下面的代码不起作用 byte b = BooleanProperty ? 2 : 3; // error 编译器说 无法将源类型“int”转换为目标类型“byte” 我知道int类型不能隐式转换为byte类型。 但是为什么前一种代码有效,而后一种代码无效呢?有一个从int常量(不仅仅是文字,还有任何int类型的编译时常量表达式)到字节的隐式转换,只要值在范围内。这来自C#5规范第6.1.9节: 隐式常量表达式转换允许以下转换: int

下面的代码可以工作

byte b = 1;
但是我注意到下面的代码不起作用

byte b = BooleanProperty ? 2 : 3; // error
编译器说

无法将源类型“int”转换为目标类型“byte”

我知道int类型不能隐式转换为byte类型。
但是为什么前一种代码有效,而后一种代码无效呢?

有一个从
int
常量(不仅仅是文字,还有任何
int
类型的编译时常量表达式)到
字节的隐式转换,只要值在范围内。这来自C#5规范第6.1.9节:

隐式常量表达式转换允许以下转换:

  • int
    类型的常量表达式(§7.19)可以转换为类型
    sbyte
    byte
    short
    ushort
    uint
    ulong
    ,前提是常量表达式的值在目标类型的范围内
但是,没有从类型为
int
的“通用”表达式到
byte
的隐式转换,这就是第二种情况下得到的结果。有点像这样:

int tmp = BooleanProperty ? 2 : 3;
byte b = tmp; // Not allowed
请注意,条件表达式的使用在推断其类型方面没有任何作用,因为第二个和第三个操作数都是
int
类型,所以整个表达式也是
int
类型

因此,如果您理解为什么上面我将代码分成两条语句的代码段不能编译,那么这就解释了为什么您的带条件语句的单行版本也不能编译

有两种修复方法:

  • 将第二个和第三个操作数更改为
    byte
    类型的表达式,以便条件表达式的总体类型为
    byte

      byte b = BooleanProperty ? (byte) 2 : (byte) 3;
    
  • 强制转换条件表达式的结果:

      byte b = (byte) (BooleanProperty ? 2 : 3);
    
说到C#

如果文本没有后缀,则它具有以下类型中的第一个 其值可以表示为:int、uint、long、ulong


编译器足够聪明,可以在
字节b=1的情况下推断出这一点文本适合字节类型。但是如果使用条件(三元)运算符
?:

我无法找到正确的C规范引用,但是当变量声明/初始化中使用的值为常量时,编译器会检查并强制将该值转换为正确的类型(假设可能)(如果不是,则为编译时错误)。由于第二个示例不是编译时常量,因此使用了一个普通表达式,其中数字的类型默认为
int
值。因此,基本上,它在某些情况下起作用是因为编译器能够明确地推断出数字将是常量且在范围内。@LasseV.Karlsen,我相信你是一个参考C#Spec的第6.1.8节,我不完全确定,因为包含初始化值的变量声明在某种程度上免除了正常的类型强制或转换规则(如果所有内容都是常量)。我认为主要原因是一件事“起作用”,另一件事“不起作用”表达式是否为100%常量(也就是说,编译器是否可以推断和计算表达式的常量值)。这是C#编译器没有多大帮助的一个领域。如果您给它一个文本数字,并且该数字在类型的范围内,那么它将接受它作为有效赋值。在所有其他情况下,编译器将这些数字强制转换为int32,然后拒绝隐式将其强制转换为正确的类型,即使该数字在范围内。这是错误的一个讨厌的问题,但它可能永远不会被修复。@LasseV.Karlsen,我想PetSerAl有它,我说的有点不对劲,如6.1.9隐式常量表达式转换所示。所有没有后缀的整数都被视为
Int32
,但编译器将隐式转换回正确的类型,如果且仅当它是一升不争论你所说的(同意它),但我发现非常奇怪的是,一个足够聪明的编译器,能够正确地推断出一些涉及泛型或lambda参数的非常复杂的表达式的类型,却不能正确地推断出三元表达式的类型。我猜编译器编写者只是从来没有想过这一点很重要。@DavidArno@LasseV.Karlsen,非常感谢您的链接。@DavidArno,太好了It’最有可能的情况是,实现该功能的成本超过了预期收益。啊,链接不起作用,因此重新发布:。不确定我做错了什么,但对此表示抱歉。