Вопрос

Выход:
Б->Привет!из явного.

Разве так не должно быть:?
А->Привет!из явного.

Почему не выполняется явное приведение (IHello) к вызову IHello.Hello() из класса A?

interface IHello
{
    void Hello();
}

class A : IHello
{

    public virtual void Hello()
    {
        Console.WriteLine("A->Hello!");
    }

    void IHello.Hello()
    {
        Console.WriteLine("A->Hello! from Explicit.");
    }
}

class B : A, IHello
{
    public override void Hello()
    {
        Console.WriteLine("B->Hello!");
    }

    void IHello.Hello()
    {
        Console.WriteLine("B->Hello! from Explicit.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new B();
        ((IHello)a).Hello();
    }
}
Это было полезно?

Решение

Нет, не должно.

Звонок в Hello эквивалентно закомментированному - путь к получению IHello не имеет значения (если только это не требует проверки или преобразования во время выполнения);тип времени компиляции просто IHello в любом случае, и отображение интерфейса такое же, как бы вы туда ни дошли.

Если интерфейс явно реализуется в иерархии типов более одного раза, используется реализация наиболее производного типа.(При вызове через интерфейс.)

Из раздела 13.4.4 спецификации С# 3.0:

Отображение интерфейса для класса или структуры C обнаруживает реализацию для каждого члена каждого интерфейса, указанного в списке базовых классов C.Реализация конкретного элемента интерфейса IM, где I является интерфейсом, в котором объявляется член M, определяется путем изучения каждого класса или структуры, начиная с C и повторяя для каждого последовательного базового класса C, пока не будет расположен матч :

  • Если S содержит заявление о явном реализации члена интерфейса, которая соответствует I и M, то этот участник является реализацией IM
  • В противном случае, если S содержит объявление нестатического открытого члена, соответствующего M, то этот член является реализацией I.M.Если совпадает более одного члена, не указано, какой из членов является реализацией I.M.Такая ситуация может возникнуть только в том случае, если S является сконструированным типом, в котором два члена, объявленные в универсальном типе, имеют разные сигнатуры, но аргументы типа делают их сигнатуры идентичными.

Другие советы

(А)а ничего не делает.Ссылка уже объявлена ​​как a, поэтому приведение ее к A не будет иметь никакого эффекта.

Несмотря на то, что ваша ссылка объявлена ​​как A, объект, на который она ссылается, имеет тип B.Если вы приведете этот объект к IHello, вызов Hello() вызовет явную реализацию Hello объекта B.

Результат точно такой, как ожидалось.

Нет, когда вы создаете новый метод (ToString), он не виртуальный.Новое просто означает, что вы не возражаете против «скрытия» версии в базовом классе - поэтому, если вы вызываете его со ссылкой, которую вы привели к определенному типу (A), он выполняет метод в классе A, независимо от фактический тип объекта, который вы вызываете.(т.е. вы вызвали A.ToString(), чтобы он выполнил A.ToString())

Когда вы создаете виртуальный метод, то независимо от того, к какому типу вы приводите ссылку, используется реализация фактического типа объекта (т. е. вы создали B, поэтому при вызове (каким бы ни был объект). Привет, он вызвал B.Hello)

Принципиальное отличие состоит в том, что один звонок виртуальный, а другой нет.

Нет, не должно.

Когда вы вызываете виртуальный метод, не имеет значения, какой тип ссылки.Вызываемый метод определяется фактическим типом объекта, а не типом ссылки.

Когда вы создаете экземпляр класса B, фактический тип объекта B.Причина, по которой он печатает "This is class A." в том, что вы не переопределили ToString метод в классе B, вы затенили его, используя new ключевое слово.Следовательно B в классе двое ToString методы, один из которых унаследован от класса A и тот, который затеняет его.Если вы используете A ссылка для вызова ToString метод, вызывается унаследованный метод, но если бы вы использовали B ссылку для ее вызова, будет вызван метод затенения и распечатается "This is class B.".

Также, если вы переопределите ToString метод в классе B вместо того, чтобы затенять его, он будет распечатывать "This is class B." независимо от типа ссылки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top