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

StackOverflow https://stackoverflow.com/questions/437926

  •  22-07-2019
  •  | 
  •  

Вопрос

У меня есть два занятия:

public class MyBase
{
    public virtual void DoMe()
    {

    }
}

public class MyDerived:MyBase
{
    public override void DoMe()
    {
        throw  new NotImplementedException();
    }
}

И у меня есть следующий код для создания экземпляра MyDerived:

        MyDerived myDerived=new MyDerived();

Дело в том, как вызвать DoMe базового класса?Если я использую myDerived.DoMe(), то будет вызван производный метод, что приведет к исключению.Я попытался привести myDerived к MyBase, но это все еще производная версия метода, который вызывается.

Редактировать:Как упоминалось в приведенном ниже комментарии, я не могу изменить ни MyDerived, ни MyBase, потому что они не являются моим кодом.

Это было полезно?

Решение

Есть решение, но оно уродливо: используйте отражение, чтобы получить метод базового класса, а затем сгенерируйте IL, необходимый для его вызова. Ознакомьтесь с этим сообщением в блоге , в котором показано, как это сделать. этот. Я успешно использовал этот подход, чтобы вызвать реализацию метода базового класса, когда все, что у меня есть, это ссылка на производный класс, который переопределяет этот метод.

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

Вы не можете вызвать версию базового класса.

Если метод не работает с производным классом, то маловероятно, что базовая версия метода будет работать при вызове экземпляра производного класса. Это просто напрашивается на неприятности. Класс не предназначен для такой работы, и то, что вы пытаетесь сделать, вероятно, приведет к непредсказуемому поведению других частей класса.

Почему вам нужно вызывать этот метод для объекта, когда объект прямо говорит вам, что он не будет работать?

Мне кажется, что у этих классов есть некоторые недостатки в дизайне, и если вам не разрешено изменять классы, возможно, вам разрешено перейти на более хорошо спроектированную библиотеку.

Чтобы вызвать MyBase.DoMe () из внешнего класса, вам потребуется либо экземпляр MyBase, либо производный экземпляр, который не переопределяет DoMe (). Метод, объявленный как виртуальный, будет вызываться для фактического типа времени выполнения объекта, а не типа объекта, поэтому приведение к MyBase не меняет вызываемый метод. Однако если бы метод не был объявлен в MyBase как виртуальный, а MyDerived все еще реализовал DoMe (), он был бы "скрыт" реализация MyBase. Поэтому, если ссылка была MyDerived, она вызывала бы MyDerived.DoMe (), но в этом случае приведение к MyBase myBase = (MyBase) myDerived и последующий вызов myBase.DoMe () вызвали бы MyBase.DoMe ().

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

Если, в отличие от вашего примера, метод в базовом классе является абстрактным, и вы должны предоставить реализацию, но не имеет смысла предоставлять ее производному классу, то, вероятно, что-то не так с дизайном классов.

public class MyDerived:MyBase{    
    public override void DoMe()    
    {        
        base.DoMe();
    }
}

Редактировать:

Вы не можете получить доступ к методу базовых классов "извне", не пройдя через метод подклассов.Ваш единственный вариант - создать экземпляр вашего базового класса напрямую и вызвать его метод.

MyBase mb = new MyBase();
mb.DoMe();

Учитывая ваши ограничения, существует другая возможность:

Загрузите .Net Reflector. Декомпилируйте существующий код, затем внесите любые изменения, необходимые для поддержки вашей ситуации.

Конечно, проверьте законность этого, прежде чем продолжить.

Этот вопрос такой старый, но я не вижу следующего варианта:

Вы можете использовать ключевое слово 'new' для указания перекрывающихся методов.Затем вы просто приведете к классу, метод которого вы хотите вызвать.

    public class MyBase
    {
        public virtual void DoMe()
        {

        }
    }

    public class MyDerived:MyBase
    {
//note the use of 'new' and not 'override'
        public new void DoMe()
        {
            throw  new NotImplementedException();
        }
    }

Реализация

var myDerived = new MyDerived();
var derivedDoMe = myDerived.DoMe();
var baseDoMe = ((MyBase)myDerived).DoMe();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top