VS2019 Roslyn编译器通用约束方法解析

时间:2019-05-17 19:25:27

标签: c# roslyn

我们最近在代码库中发现了一个问题,其中VS2019编译的代码很好,但VS 2017失败了。

我为Union创建了一个扩展方法,该方法具有一个通用ISet作为通用约束

using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
    public static S Union<S, T>(this S self, IEnumerable<T> other) where S : ISet<T>, new()
    {
        //For simplicity issues since this is a compilation based question
        return default(S);
    }

    public static void Test()
    {
        var values = new[] { 1, 2, 3 };
        var values1 = new[] { 1, 2, 3, 4 };

        values.Union(values1);
    }
}

联合会产生一个编译错误,指出int []无法转换为ISet。

据我了解,方法解析最初忽略了通用约束。但似乎这段代码会在2019年编译。

我在发行说明中没有看到任何地方指出他们已经解决了该错误或添加了新功能来改善通用方法的方法分辨率。

我正在寻找有关此事的更多信息, 这是Microsoft的错误修复程序还是预期的功能?

1 个答案:

答案 0 :(得分:4)

它是C#7.3的一部分(因此,如果您指定7.3版,则也可以在VS 2017中使用它)。它记录在C# 7.3 release notes中:

  

改进的超负荷候选者

     

在每个版本中,重载解决规则都会更新,以解决模棱两可的方法调用具有“明显”选择的情况。此版本添加了三个新规则,以帮助编译器选择显而易见的选择:

     
      
  1. ...
  2.   
  3. 当方法组包含一些类型参数不满足其约束的通用方法时,这些成员将从候选集中删除。
  4.   
  5. ...
  6.   

这以前不是错误-遵守语言规范;我不知道为什么规范最初是按照这里的方式编写的。可能的原因包括:

  • 预期的实现复杂度
  • 预期的实施效果
  • 预期的有用性-预期先前的行为会比当前的行为好甚至更好,而不会意识到现实中会令人烦恼的地方