.NET 6下C#编译器类型推断异常及重载歧义问题咨询
问题原因解析
1. 无Action<double>重载时匹配Action<long>的原因
C#编译器在重载决议阶段会优先寻找可行重载——即能让代码逻辑合法的重载。当你调用SetValue(v => { /* 操作double变量 */ })且没有Action<double>重载时:
- 编译器会尝试推导lambda参数
v的类型,此时唯一的数值类型重载是Action<long> - 把
v推导为long后,long类型值可以隐式转换为double(double取值范围覆盖long,且整数转换不会丢失精度),函数体的赋值操作完全合法 - 编译器判定该重载可行,因此不会报错,直接选择
Action<long>版本
2. 添加Action<double>后出现歧义的原因
当同时存在Action<long>和Action<double>两个重载时,编译器需要判断哪个重载更适配当前调用:
- 对于
Action<long>:lambda参数v被推导为long,赋值给double变量是合法的隐式转换 - 对于
Action<double>:lambda参数v被推导为double,赋值给double变量是精确匹配,逻辑同样合法 - 根据C#重载决议规则,这两个重载之间不存在更优的转换路径——既不能判定
Action<long>比Action<double>更匹配,也无法反过来 - 编译器无法自动识别你的意图,因此抛出
CS0121歧义错误
3. 消除歧义的原理
显式指定类型(比如SetValue((double v) => { ... })或SetValue((Action<double>)(v => ...)))相当于给编译器明确的目标重载提示,直接跳过类型推导阶段,自然消除了歧义。
内容的提问来源于stack exchange,提问作者White
相关产品推荐
相关产品推荐

