Как я могу запретить вызов базового конструктора наследником в C#?
-
03-07-2019 - |
Вопрос
У меня есть (плохо написанный) базовый класс, который я хочу обернуть в прокси-объект.Базовый класс выглядит следующим образом:
public class BaseClass : SomeOtherBase
{
public BaseClass() {}
public BaseClass(int someValue) {}
//...more code, not important here
}
и мой прокси выглядит так:
public BaseClassProxy : BaseClass
{
public BaseClassProxy(bool fakeOut){}
}
Без конструктора «fakeOut» ожидается вызов базового конструктора.Однако при этом я ожидал, что его не вызовут.В любом случае мне нужен либо способ не вызывать конструкторы базового класса, либо какой-то другой способ эффективно проксировать этот (злой) класс.
Решение
Если вы не вызываете явно какой-либо конструктор в базовом классе, конструктор без параметров будет вызван неявно.Обойти это невозможно: вы не можете создать экземпляр класса без вызова конструктора.
Другие советы
Существует способ создать объект без вызова любой конструкторы экземпляров.
Прежде чем продолжить, убедитесь, что вы хотите сделать это именно так.В 99% случаев это неправильное решение.
Вот как вы это делаете:
FormatterServices.GetUninitializedObject(typeof(MyClass));
Вызовите его вместо конструктора объекта.Он создаст и вернет вам экземпляр без вызова каких-либо конструкторов или инициализаторов полей.
Когда вы десериализуете объект в WCF, он использует этот метод для создания объекта.Когда это происходит, конструкторы и даже инициализаторы полей не запускаются.
Должен быть вызван как минимум 1 актер.Единственный способ обойти это, я вижу, это сдерживание.Имейте класс внутри или ссылайтесь на другой класс.
Если то, что вы хотите, это нет вызвать любой из двух конструкторов базового класса, это невозможно сделать.
Конструкторы классов C# должны вызывать конструкторы базовых классов.Если вы не вызываете его явно, база( ) подразумевается.В вашем примере, если вы не укажете, какой конструктор базового класса вызывать, это будет то же самое, что:
public BaseClassProxy : BaseClass
{
public BaseClassProxy() : base() { }
}
Если вы предпочитаете использовать другой конструктор базового класса, вы можете использовать:
public BaseClassProxy : BaseClass
{
public BaseClassProxy() : base(someIntValue) { }
}
В любом случае, одно из двух воля вызываться явно или неявно.
Я не верю, что можно обойтись без вызова конструктора.Но вы могли бы сделать что-то вроде этого:
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
}
}
Когда вы создаете объект BaseClassProxy, ему НЕОБХОДИМО создать экземпляр его базового класса, поэтому вам нужно вызвать конструктор базового класса, что вы можете сделать, это выбрать, какой из них вызывать, например:
public BaseClassProxy (bool fakeOut) : base (10) {}
Чтобы вызвать второй конструктор вместо первого
Я боюсь, что конструктор базовых вызовов не является вариантом.
В итоге я сделал что-то вроде этого:
public class BaseClassProxy : BaseClass
{
public BaseClass BaseClass { get; private set; }
public virtual int MethodINeedToOverride(){}
public virtual string PropertyINeedToOverride() { get; protected set; }
}
Это помогло мне преодолеть некоторые плохие практики базового класса.
конструкторы являются общедоступными по своей природе.не используйте конструктор, а используйте другой для создания и сделайте его частным. Таким образом, вы создадите экземпляр без параметров и вызовете эту функцию для создания экземпляра вашего объекта.
Хорошо, вот уродливое решение проблемы, когда один класс наследует конструкторы другого класса, и я не хотел, чтобы некоторые из них работали. Я надеялся избежать использования этого в своем классе, но вот оно:
Вот мой конструктор класса:
public MyClass();
{
throw new Exception("Error: Must call constructor with parameters.");
}
Хорошо, теперь вас предупредили, что это некрасиво.Никаких жалоб, пожалуйста!
Я хотел получить хотя бы минимальные параметры из моего основного конструктора, не допуская при этом унаследованный базовый конструктор без параметров.
Я также считаю, что если вы создадите конструктор и не поместите:base() после него, что он не будет вызывать конструктор базового класса. И если вы создадите конструкторы для всех конструкторов базового класса и предоставите им одинаковые параметры в основном классе, это не пройдет.Но это может быть утомительно, если в базовом классе много конструкторов!