Разрешение перегрузки выбирает несовместимый универсальный метод вместо совместимого метода базового класса - PullRequest
3 голосов
/ 10 декабря 2011

Я столкнулся с проблемой разрешения перегрузки, которую я не ожидал. По-видимому, компилятор скорее разрешает вызов метода MyPrint, передавая "Hello world" MyPrint<T>(T : struct) в производном классе, чем MyPrint(string), определенному в базовом классе. И поскольку метод, выбранный преобразователем, не будет принимать строку, я получаю ошибку компилятора.

Полагаю, это связано с проблемой хрупкого базового класса, как Джон Скит написал в своей книге и Эрик Липперт в своем блоге . Липперт цитирует стандарт так:

Методы в базовом классе не являются кандидатами, если какой-либо метод в производном класс применим.

Но я не вижу применимости какого-либо метода в производном классе, равно как и компилятор, судя по ошибке. Я хотел бы знать две вещи: почему это работает таким образом, и как я могу позволить 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 ]

2 голосов
/ 10 декабря 2011

Вы уже нашли половину причины, но вам также нужно Ограничения не являются частью подписи. В сочетании с «Методы в базовом классе не являются кандидатами, если применим какой-либо метод в производном классе» вы получаете, что во время разрешения перегрузки есть два метода, которые выглядят как MyPrint(string) и, следовательно, применимы, так что выбирается тот, который находится в наиболее производном классе. Только после этого проверяется ограничение, которое затем не выполняется.

0 голосов
/ 10 декабря 2011

Вы можете заставить это работать, если вы определите это в своем производном классе:

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

Что касается "почему", извините, я не знаю.Возможно, Спецификация языка C # может помочь ответить на этот вопрос.

...