相同C#版本下代码在Visual Studio 2019与2012的编译行为差异问题
编译行为差异的核心原因
即使你在两个IDE中都指定了C# 5.0语言版本和.NET Framework 4.5运行时,两者使用的编译器核心完全不同:
- VS2012使用的是原生C# 5.0编译器,是微软推出的旧版非托管编译器
- VS2019使用的是Roslyn编译器,是微软从VS2015开始启用的新一代托管编译器,你指定C# 5.0语言版本只是限制了可使用的语法特性,不会改变编译器本身的基础逻辑规则
你碰到的歧义场景属于重载决议的边缘处理差异:HandleMessages是返回Task的方法组,它可以同时隐式转换为两种委托类型:
Action:忽略方法的返回值,仅执行调用逻辑Func<Task>:完整匹配方法的签名,保留返回的Task对象
旧版VS2012的C#编译器判定这两种隐式转换的优先级相同,因此抛出调用不明确的错误。而Roslyn编译器对方法组转换的重载决议逻辑做了优化,会优先选择匹配返回值的Func<Task>重载,因此不会报错。
对齐VS2012编译行为的配置方法
如果你需要让VS2019的编译结果和旧版环境完全一致,避免本地编译通过但服务器/旧IDE编译失败的问题,可以在项目的.csproj文件的PropertyGroup节点中添加如下配置:
<Features>strict-overload-resolution=true</Features>
开启该配置后,Roslyn编译器会启用旧版的重载决议规则,碰到同类歧义场景会和VS2012一样抛出编译错误。
额外优化建议
你当前使用的Task.Factory.StartNew<Task>(HandleMessages)修复方案是可行的,更推荐你使用Task.Run(HandleMessages)替换原有调用,该方法对返回Task的异步委托有专属重载,天生不存在歧义问题,兼容性更强。
内容的提问来源于stack exchange,提问作者Saadat Al-KayyaLi
相关产品推荐
相关产品推荐

