当 aushort?
被传递给Assert.Equal
它时,它试图将两个参数转换为string
。它适用于int?
. 如果我将代码更改为ushort test = 10;
or Assert.Equal((ushort)10, test);
或Assert.Equal(10, (ushort)test);
它工作正常。这是什么原因?可能是因为ushort
and both char
is 2 bytes 并且Assert.Equal
隐含地试图将其ushort?
视为字符串吗?
1 回答
请注意,虽然存在从10
to的隐式转换ushort?
ushort? foo = 10;
这只适用于常量表达式10
在 的范围内ushort
,并且应用了隐式常量表达式转换。
Equal
方法组具有通用方法,例如您尝试调用的方法。所以在重载决议开始之前,类型推断发生了。
类型推断作为方法调用的绑定时处理的一部分发生,并且发生在调用的重载解决步骤之前。如果在方法调用中指定了特定方法组,并且没有将类型参数指定为方法调用的一部分,则类型推断将应用于方法组中的每个泛型方法。[...] 如果特定方法的类型推断失败,则该方法不参与重载决议。
在这种情况下,所有泛型重载的类型推断实际上都失败了,因此它们不参与重载决策。Equal(string, string)
是重载之一。这就是错误消息与字符串重载有关的原因。
为什么类型推断会失败?因为没有从int
toushort?
或 from ushort?
to的隐式转换int
。类型推断只关心参数、形参和类型参数的类型。它不关心参数是常量表达式还是类似的东西,所以前面提到的隐式常量表达式转换不适用。我鼓励您遵循规范中的类型推断过程。很有趣 :)
请参阅此处对“类型Ei
”的引用:
对于每个方法参数
Ei
:
- [...]
- 否则,如果
Ei
具有类型U
并且是值参数,则从toxi
进行下限推断。U
Ti
- [...]
将此与它在重载解析中引用“参数”而不是“参数类型”的方式进行比较:
对于 中的每个实
A
参,实参的传参方式(即值、ref
或out
)与对应形参的传参方式相同,且
- 对于值形参或形参数组,存在从实参到对应形参类型的隐式转换,或
- [...]
因此,重载决议似乎确实会查看参数的表达式,这就是为什么如果您将方法设为非泛型并接受两个ushort?
. 在那种情况下,它不参与类型推断,只参与重载决议。
强制转换10
toushort
或起作用的原因是,在 from to和 from tobyte
之间确实存在隐式转换。这是通过隐式可空转换完成的。ushort
ushort?
byte
ushort?