如何防止基构造函数被 C# 中的继承者调用
本文关键字:继承者 调用 何防止 构造函数 | 更新日期: 2023-09-27 17:47:23
我有一个(写得不好的)基类,我想把它包装在一个代理对象中。基类类似于以下内容:
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 个 ctor。我看到的唯一解决方法是遏制。将类放在内部或引用其他类。
我不相信你可以绕过调用构造函数。 但是你可以做这样的事情:
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
}
}
如果你想要的是不调用两个基类构造函数中的任何一个,则无法执行此操作。
C# 类构造函数必须调用基类构造函数。如果你没有显式调用一个,则暗示 base( )。在您的示例中,如果未指定要调用的基类构造函数,则它与
:public BaseClassProxy : BaseClass
{
public BaseClassProxy() : base() { }
}
如果更喜欢使用其他基类构造函数,可以使用:
public BaseClassProxy : BaseClass
{
public BaseClassProxy() : base(someIntValue) { }
}
无论哪种方式,都将显式或隐式调用两者之一。
当你创建一个 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; }
}
这让我绕过了基类的一些不良做法。
使其 private.so 您将创建一个没有参数的实例并调用该函数来构造对象实例。
好吧,这是一个丑陋的解决方案,解决一个类继承另一个类的构造函数的问题,我不想让其中一些类工作。我希望避免在我的课堂上使用它,但这里是:
这是我的类构造函数:
public MyClass();
{
throw new Exception("Error: Must call constructor with parameters.");
}
好吧,现在你被警告说它很丑。请不要抱怨!
我想至少从我的主构造函数中强制使用最少的参数,而不允许继承的基构造函数没有参数。
我还相信,如果你创建一个构造函数并且不把 : base() 放在它后面,它就不会调用基类构造函数。如果您为基类中的所有构造函数创建构造函数,并在主类中为它们提供相同的确切参数,则它不会传递。但是,如果基类中有很多构造函数,这可能会很乏味!
可以在不调用无参数构造函数的情况下创建一个对象(请参阅上面的答案)。但是我使用这样的代码来创建基类和继承类,在其中我可以选择是否执行基类的 init。
public class MyClass_Base
{
public MyClass_Base()
{
/// Don't call the InitClass() when the object is inherited
/// !!! CAUTION: The inherited constructor must call InitClass() itself when init is needed !!!
if (this.GetType().IsSubclassOf(typeof(MyClass_Base)) == false)
{
this.InitClass();
}
}
protected void InitClass()
{
// The init stuff
}
}
public class MyClass : MyClass_Base
{
public MyClass(bool callBaseClassInit)
{
if(callBaseClassInit == true)
base.InitClass();
}
}
解决问题的方法
using System;
public class Program
{
public static void Main()
{
Console.WriteLine(new Child().Test);
}
public class Child : Parent {
public Child() : base(false) {
//No Parent Constructor called
}
}
public class Parent {
public int Test {get;set;}
public Parent()
{
Test = 5;
}
public Parent(bool NoBase){
//Don't do anything
}
}
}
一个简单优雅的解决方案。您可以根据需要进行更改。
我的另一个简单解决方案:
class parent
{
public parent()
{
//code for all children
if (this.GetType() == typeof(child1))
{
//code only for objects of class "child1"
}
else
{
//code for objects of other child classes
}
}
}
class child1 : parent
{
public child1()
{}
}
// class child2: parent ... child3 : parent ... e.t.c