为什么 Roslyn 不会为方法统一抛出错误?

Why does Roslyn not throw an error for method unification?

如果您尝试实现两个可能 "unify" 一组特定类型参数的接口,Roslyn 将抛出错误:

public interface IFoo<T1, T2>
{
    void Method(T1 a, T2 b);
}

public class Foo<T1, T2> : IFoo<T1, T2>, IFoo<T2, T1>
{
    public void Method(T2 a, T1 b) { }
    public void Method(T1 a, T2 b) { }
}

Foo class 不会编译并且 Roslyn 会给你一个错误说“Foo<T1, T2> 不能同时实现 IFoo<T1, T2>IFoo<T2, T1> 因为它们可能会统一某些类型参数替换。”即使对于大多数类型替换都没有问题,Roslyn 甚至不允许您声明这个 class 因为有人可能使用类型替换,其中 T1 == T2.

但是,编译器可以让你这样声明:

public class Bar<T1, T2>
{
    public void Method(T1 t) { }
    public void Method(T2 t) { }
}

此 class 编译正常,只有在客户端尝试调用该方法时才会抛出错误:

var bar = new Bar<int, int>();
bar.Method(5);

这里Roslyn报错说"This call is ambiguous between the following methods or properties: Bar<T1, T2>.Method(T1) and Bar<T1, T2>.Method(T2)."

我想知道为什么在这两种非常相似的情况下编译器的行为如此不同。编译器是否应该在您声明两个可能统一的方法时立即抛出错误?

可以调用每个单独的Bar.Method方法:

public class Bar<T1, T2> {
    public void Method(T1 t) {
        Console.WriteLine("FirstMethod");
    }
    public void Method(T2 t) {
        Console.WriteLine("SecondMethod");
    }
}
public static void CallFirstMethod<T1, T2>(Bar<T1, T2> bar, T1 t) {
    bar.Method(t);
}
public static void CallSecondMethod<T1, T2>(Bar<T1, T2> bar, T2 t) {
    bar.Method(t);
}
public static void Test() {
    var bar = new Bar<int, int>();
    CallFirstMethod(bar, 5);
    CallSecondMethod(bar, 6);
}

因此,在这种情况下没有理由产生错误。