C# 在C中调用基构造函数#
我有以下层次结构:C# 在C中调用基构造函数#,c#,asp.net,C#,Asp.net,我有以下层次结构: class Base { public Base(string sMessage) { //Do stuff } } class Derived : Base { public Derived(string someParams) { string sMessage = "Blah " + someParams; //Here I want to call the base constructor //base(sMess
class Base
{
public Base(string sMessage)
{
//Do stuff
}
}
class Derived : Base
{
public Derived(string someParams)
{
string sMessage = "Blah " + someParams;
//Here I want to call the base constructor
//base(sMessage);
}
}
你不能。您可以在之前调用它:
public Derived() : base()
或者你必须用钩子
class Base
{
protected void init() { }
public Base(string sMessage)
{
init();
}
}
class Derived : Base
{
public Derived(string someParams)
{
string sMessage = "Blah " + someParams;
init();
}
}
你必须这样做。您也许可以将要在以后调用的代码放在基类中的受保护方法中,然后可以像这样在以后调用它:
class Base
{
public Base(string sMessage)
{
ConstructorStuff();
}
protected Base()
{
}
protected void ConstructorStuff()
{
}
}
class Derived : Base
{
public Derived(string someParams)
{
string sMessage = "Blah " + someParams;
ConstructorStuff();
}
}
施工人员应注意的事项: ·构造函数不能是“虚拟的” ·它们不能被继承 ·构造函数是按继承顺序调用的
public Child(string a):base(a){}
必须在派生类构造函数的主体之前调用基类构造函数
class Derived : Base
{
public Derived(string someParams)
: base("Blah " + someParams)
{
}
}
如果确实需要首先运行构造函数,那么我建议使用受保护的初始化方法,该方法由构造函数调用,并执行初始化类的实际工作。您需要提供一个备用构造函数,允许跳过初始化
public class Base
{
public Base() : this(true) { }
protected Base(bool runInitializer)
{
if (runInitializer)
{
this.Initialize();
}
}
protected void Initialize()
{
...initialize...
}
}
public class Derived : Base
{
// explicitly referencing the base constructor keeps
// the default one from being invoked.
public Derived() : base(false)
{
...derived code
this.Initialize();
}
}
实际上,最简单的解决方案是:
class Base
{
public Base(string sMessage)
{
//Do stuff
}
}
class Derived : Base
{
public Derived(string someParams)
: base("Blah " + someParams)
{
}
}
为什么要把它弄得更复杂?我最初错过了OregonGhost关于使用静态方法修改参数的评论,这对我来说是最有用的,所以我想我应该为阅读此线程的其他人添加一个代码示例:
class Base
{
public Base( string sMessage )
{
// Do stuff
}
}
class Derived : Base
{
public Derived( string sMessage ) : base( AdjustParams( sMessage ) )
{
}
static string AdjustParams( string sMessage )
{
return "Blah " + sMessage;
}
}
既然基本构造函数应该做一些事情(可能是一些与sMessage有关的事情),那么这段代码如何解决他的问题呢?如果你使用钩子,你需要有一种避免调用默认基本构造函数的方法。请参阅我的答案,了解通过提供不运行初始值设定项的构造函数来避免此问题的方法。@wcm:我只是展示实现DotnetDude所需操作顺序的步骤。看起来他对C#非常了解,可以在这里修改参数并返回对象以满足他的实际需要。@Dinah——如果没有默认构造函数,这甚至无法编译。如果添加调用init()的默认构造函数,那么init()将被调用两次:一次在基构造函数中,一次在派生构造函数中。如果使用钩子实现,则需要有一个不运行它的构造函数。这将运行ConstructorStuff两次——一次是在派生构造函数之前调用默认基构造函数时,一次是在派生构造函数执行期间。Erm?Base没有调用ConstructorStuff的默认构造函数?啊。然后您需要提供一个默认构造函数,否则代码将无法编译,因为您的派生类将需要它。问题仍然存在,默认构造函数也需要使用ConstructorStuff,并且您需要一个不调用初始值设定项的替代方法。这将使我了解到,我遗漏了一个基本C#问题中的“太明显而不麻烦”代码。修改后的代码可以做他想做的事情,不是吗?现在的问题是每个派生类都需要调用初始值设定项。我认为您想要的是在默认情况下运行initialize,但在必要时有一种方法来阻止它。这可以完成任务,但不是IMO的最佳解决方案。对于这种简单的情况,这可能是最好的解决方案,但如果构造参数要复杂得多,它会很快变得难看。这是事实,尽管您也可以在静态方法中构造参数,并将结果传递给基类构造函数。我更喜欢这种方法。或者,由于这是.NET,您可以从构造函数中删除内容并在setters中执行,这是序列化友好的。是的,我注意到OregonGhost已经提出了这一点。。
class Base
{
public Base( string sMessage )
{
// Do stuff
}
}
class Derived : Base
{
public Derived( string sMessage ) : base( AdjustParams( sMessage ) )
{
}
static string AdjustParams( string sMessage )
{
return "Blah " + sMessage;
}
}