同LangVersion7.3下,VS2019报CS0165而VS2022无错的原因?
问题解答:CS0165错误在不同Roslyn版本的差异分析
测试代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CS0165 { internal class Program { static void Main(string[] args) { Function(null); } static string Function(IDictionary<string, string> dict) { if (dict?.TryGetValue("A", out var value1) ?? false) return value1; // <-- VS2019中报错 if(dict?.TryGetValue("A", out var value2) == true) return value2; // <-- VS2019中报错 if (dict != null && dict.TryGetValue("A", out var value3)) return value3; return null; } } }
问题分析与解答
1. 关于“变量确定赋值规则属于语言规范内容,理论上不应因编译器版本更智能而产生差异”的结论是否正确?
这个结论不完全准确。语言规范确实定义了确定赋值的规则,但编译器对规范的实现可能存在疏漏或bug,尤其是早期版本的编译器可能未覆盖所有复杂场景的分析逻辑。对于dict?.TryGetValue(...) ?? false或dict?.TryGetValue(...) == true这类null条件运算符结合out变量的场景,旧版本Roslyn的确定赋值分析逻辑存在不足,没能正确识别:当条件为true时,dict必然非null,且TryGetValue已执行并完成out变量的赋值。
2. 是否只要编译器支持并使用LangVersion7.3,同版本语言的代码就能在任意编译器版本中无错编译?
不一定。/langversion参数主要控制语言特性的可用性(比如是否允许使用C#7.3的语法),但无法保证不同编译器版本对规范的实现完全一致。旧版本编译器可能存在未修复的分析bug,导致符合规范的代码被误判;新版本编译器修复了这些bug后,就能正确编译同一段代码。也就是说,同LangVersion下,编译结果可能因编译器版本不同而存在差异,这是编译器迭代完善过程中的正常现象。
3. 这是否属于旧/新版本编译器的bug?
旧版本Roslyn(3.11.0-4.22108.8)存在确定赋值分析的bug,误报了CS0165错误;新版本(4.5.2-3.23171.7)修复了这个bug,能够正确识别out变量在条件为true时已经被赋值。这类情况属于早期编译器实现的边界场景疏漏,后续版本通过修复完善了对语言规范的执行。
内容的提问来源于stack exchange,提问作者user221592
相关产品推荐
相关产品推荐

