Принудительный вызов базового метода извне производного класса - PullRequest
5 голосов
/ 13 января 2009

У меня есть два класса:

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, но это все еще производная версия метода, которая вызывается.

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

Ответы [ 7 ]

3 голосов
/ 17 ноября 2009

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

3 голосов
/ 13 января 2009

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

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

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

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

0 голосов
/ 14 ноября 2015

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

Вы можете использовать ключевое слово '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();
0 голосов
/ 16 января 2009

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

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

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

0 голосов
/ 13 января 2009

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

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

0 голосов
/ 13 января 2009

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

0 голосов
/ 13 января 2009
public class MyDerived:MyBase{    
    public override void DoMe()    
    {        
        base.DoMe();
    }
}

EDIT:

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

MyBase mb = new MyBase();
mb.DoMe();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...