Как я могу предотвратить вызов базового конструктора наследником в C #? - PullRequest
21 голосов
/ 01 октября 2008

У меня есть (плохо написанный) базовый класс, который я хочу обернуть в объект прокси. Базовый класс напоминает следующее:

public class BaseClass : SomeOtherBase 
{
   public BaseClass() {}

   public BaseClass(int someValue) {}

   //...more code, not important here
}

и мой прокси напоминает:

public BaseClassProxy : BaseClass
{
  public BaseClassProxy(bool fakeOut){}
}

Без конструктора "fakeOut" ожидается вызов базового конструктора. Однако, с этим, я ожидал, что это не будет названо. В любом случае, мне либо нужен способ не вызывать конструкторы базового класса, либо какой-либо другой способ эффективно проксировать этот (злой) класс.

Ответы [ 10 ]

56 голосов
/ 02 октября 2008

Существует способ создать объект без вызова любых конструкторов экземпляров.

Прежде чем продолжить, убедитесь, что вы хотите сделать это таким образом. 99% времени это неправильное решение.

Вот как вы это делаете:

FormatterServices.GetUninitializedObject(typeof(MyClass));

Назовите его вместо конструктора объекта. Он создаст и вернет вам экземпляр без вызова каких-либо конструкторов или инициализаторов полей.

Когда вы десериализуете объект в WCF, он использует этот метод для создания объекта. Когда это происходит, конструкторы и даже инициализаторы полей не запускаются.

19 голосов
/ 01 октября 2008

Если вы не вызовете явно конструктор в базовом классе, конструктор без параметров будет вызван неявно. Обойти это невозможно, вы не можете создать экземпляр класса без вызова конструктора.

6 голосов
/ 01 октября 2008

Должен быть вызван как минимум 1 ctor. Я вижу единственный способ обойти это сдерживание. Имейте класс внутри или ссылаясь на другой класс.

5 голосов
/ 01 октября 2008

Если вы хотите , а не , вызвать один из двух конструкторов базового класса, это невозможно сделать.

Конструкторы класса C # должны вызывать конструкторы базового класса. Если вы не вызываете его явно, подразумевается base () . В вашем примере, если вы не укажете, какой конструктор базового класса вызывать, он будет таким же, как:

public BaseClassProxy : BaseClass
{
    public BaseClassProxy() : base() { }
}

Если вы предпочитаете использовать конструктор другого базового класса, вы можете использовать:

public BaseClassProxy : BaseClass
{
    public BaseClassProxy() : base(someIntValue) { }
}

В любом случае, один из двух будет вызываться, явно или неявно.

4 голосов
/ 01 октября 2008

Я не верю, что вы можете обойтись вызовом конструктора. Но вы могли бы сделать что-то вроде этого:

public class BaseClass : SomeOtherBase 
{
   public BaseClass() {}

   protected virtual void Setup()
   {
   }
}

public BaseClassProxy : BaseClass
{
   bool _fakeOut;
   protected BaseClassProxy(bool fakeOut)
   {
        _fakeOut = fakeOut;
        Setup();
   }

   public override void Setup()
   {
       if(_fakeOut)
       {
            base.Setup();
       }
       //Your other constructor code
   }
} 
1 голос
/ 01 октября 2008

Когда вы создаете объект BaseClassProxy, ему НУЖНО создать экземпляр его базового класса, поэтому вам нужно вызвать конструктор базового класса, что вы можете сделать, это выбрать один из них для вызова, например:

public BaseClassProxy (bool fakeOut) : base (10) {}

Для вызова второго конструктора вместо первого

1 голос
/ 01 октября 2008

Я боюсь, что не базовый конструктор вызова не вариант.

0 голосов
/ 29 марта 2018

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

Вот мой конструктор класса:

public MyClass();
{
   throw new Exception("Error: Must call constructor with parameters.");
}

Хорошо, теперь вас предупредили, что это ужасно. Без претензий, пожалуйста!

Я хотел получить хотя бы минимальные параметры из моего основного конструктора, не допуская при этом наследуемого базового конструктора без параметров.

Я также считаю, что если вы создаете конструктор и не ставите после него: base (), он не будет вызывать конструктор базового класса. И если вы создаете конструкторы для всех из них в базовый класс и предоставьте те же точные параметры для них в основном классе, что он не пройдет. Но это может быть утомительно, если в базовом классе много конструкторов!

0 голосов
/ 21 ноября 2011

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

0 голосов
/ 01 октября 2008

Я закончил тем, что делал что-то вроде этого:

public class BaseClassProxy : BaseClass 
{
   public BaseClass BaseClass { get; private set; }

   public virtual int MethodINeedToOverride(){}
   public virtual string PropertyINeedToOverride() { get; protected set; }
}

Это помогло мне справиться с некоторыми из плохих практик базового класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...