C#规范中为何禁止二元运算符将ulong提升为float?
C# ulong与int二元运算的绑定疑惑解析
核心问题拆解
为什么ulong和int都能隐式转成float,调用fn(float, float)可以直接传这两个类型的参数,但ulong + int却无法自动提升为float + float运算?
规范里的关键规则(非信息性部分)
问题的核心在于运算符重载解析的候选集筛选逻辑和方法调用的参数适配逻辑完全不同:
- 方法调用的逻辑是:先找到目标方法签名,再检查参数是否能通过隐式转换适配该签名,所以
int和ulong能转成float来匹配fn(float, float)。 - 但二元运算符的解析逻辑是:先根据操作数的原始类型确定候选运算符集合,这个集合只包含预定义的、与操作数类型组匹配的运算符(包括同组内的数值提升形式),不会跨组考虑其他类型的运算符。
类型组与候选集的隐含规则
从乘法运算符的分组(整数、浮点数、decimal)就能看出,C#的预定义运算符是按类型组划分的:
- 整数组:包含所有有符号/无符号整数类型,组内支持数值提升(比如
int和long运算会提升为long)。 - 浮点数组:包含
float、double。 - Decimal组:仅
decimal类型。
ulong属于无符号整数组,int属于有符号整数组,两者的共同候选运算符里没有直接运算的版本,也不会自动跨组转换为float来匹配浮点数组的float + float运算符——因为候选集的筛选规则根本不会把跨组的运算符纳入考虑范围。
规范依据
二元运算符重载解析章节提到的「预定义运算符(含提升形式)」,这里的提升仅指同类型组内的数值提升,比如有符号整数之间的提升、无符号整数之间的提升,而非跨组转换为浮点类型。虽然规范没有单独把类型组的规则列出来,但通过各个运算符的描述(比如乘法的分组)可以明确:候选运算符只会从操作数所属类型组的预定义运算符中选择,这就是ulong + int无法绑定到float + float的根本原因。
内容的提问来源于stack exchange,提问作者Brad Robinson
相关产品推荐
相关产品推荐

