重载决策选择不兼容的泛型方法而不是兼容的基类方法

时间:2011-12-10 18:25:22

标签: c# overloading

我遇到了一个我没想到的超载解决问题。显然,编译器解析了对MyPrint方法的调用,该方法将"Hello world"传递给派生类中的MyPrint<T>(T : struct)而不是基类中定义的MyPrint(string)。由于解析器选择的方法不接受字符串,因此出现编译错误。

我认为它与Jon Skeet wrote in his bookEric Lippert on his blog这个脆弱的基类问题有关。 Lippert引用标准说:

  

如果派生中的任何方法,基类中的方法不是候选者   课程适用。

但是我没有看到派生类中的任何方法适用,编译器也没有从错误中判断出来。我想知道两件事:为什么它以这种方式工作,我怎样才能让C#做我想要它做的事呢?

证明问题的成功案例:

class Program
{
    static void Main(string[] args)
    {
        Derived d = new Derived();

        d.MyPrint(10);

        // ERROR: The type 'string' must be a non-nullable value type
        // in order to use it as parameter 'T'
        // in the generic type or method 'Derived.MyPrint<T>(T)'.
        d.MyPrint("Hello world!");
    }
}

class Base
{
    // I print only strings.
    public void MyPrint(string value)
    {
        Console.WriteLine("String: " + value);
    }
}

class Derived : Base
{
    // I print any primitive type, enums and DateTime,
    // but NOT string (since that is not a value type).
    public void MyPrint<T>(T value)
        where T : struct, IConvertible
    {
        Console.WriteLine("IConvertible: " + value.ToString());
    }
}

2 个答案:

答案 0 :(得分:2)

你已经找到了一半的原因,但是你还需要Constraints are not part of the signature.结合“如果派生类中的任何方法适用,基类中的方法不是候选者”,你可以在重载解析过程中得到它两个看起来像MyPrint(string)的方法因此适用,因此选择了派生程度最高的类中的方法。只有在那之后才检查约束,然后失败。

答案 1 :(得分:0)

如果你在派生类中定义它,你可以使它工作:

public new void MyPrint(string value)
{
    base.MyPrint(value);
}

至于“为什么”,抱歉我不知道。可能C# Language Specification可以帮助回答这个问题。