【问题标题】:Overload resolution picks incompatible generic method instead of compatible base class method重载解析选择不兼容的泛型方法而不是兼容的基类方法
【发布时间】:2012-01-17 12:47:51
【问题描述】:

我遇到了一个我没想到的重载解决问题。显然,编译器宁愿解析对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());
    }
}

【问题讨论】:

  • MyPrint 在重载解析期间看起来像 MyPrint,然后由于不满足约束而失败。我猜是“约束不是签名的一部分”的结果
  • 最好将其作为答案而不是评论

标签: c# overloading


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您已经找到了一半的原因,但您还需要Constraints are not part of the signature. 结合“如果派生类中的任何方法适用,则基类中的方法不是候选方法”,您会发现在重载解决期间有两种方法看起来像MyPrint(string) 并因此适用,因此选择最派生类中的那个。只有在那之后才检查约束,然后失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-28
      • 2019-01-10
      • 2015-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-16
      • 1970-01-01
      相关资源
      最近更新 更多