在 C# 中调用基本构造函数 [重复]

Posted

技术标签:

【中文标题】在 C# 中调用基本构造函数 [重复]【英文标题】:Calling base constructor in C# [duplicate] 【发布时间】:2010-10-12 05:21:49 【问题描述】:

我有以下层次结构:

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);

  


【问题讨论】:

【参考方案1】:

我最初错过了 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;
    

【讨论】:

【参考方案2】:

其实最简单的解决办法是:

class Base

  public Base(string sMessage)
  
     //Do stuff
  


class Derived : Base

  public Derived(string someParams)
    : base("Blah " + someParams)
  
  


为什么要让它更复杂?

【讨论】:

是的,我注意到之后 OregonGhost 已经建议了这个..【参考方案3】:
public Derived(string someParams) : base(someParams)

    string sMessage = "Blah " + someParams;

这是你必须这样做的方式。你也许可以把你想调用的代码放在基类的一个受保护的方法中,然后你可以像这样调用它:

class Base

  public Base(string sMessage)
  
     ConstructorStuff();
  

  protected Base()
  
  

  protected void ConstructorStuff()
  
  


class Derived : Base

  public Derived(string someParams)
      
   string sMessage = "Blah " + someParams;

   ConstructorStuff();       
      

【讨论】:

这将运行 ConstructorStuff 两次——一次是在派生构造函数之前调用默认基本构造函数时,一次是在派生构造函数执行期间。 呃? Base 没有调用 ConstructorStuff 的默认构造函数? 啊。然后您需要提供一个默认构造函数,否则代码将无法编译,因为您的派生类将需要它。问题仍然存在,默认构造函数也需要使用 ConstructorStuff 并且您需要一个不调用初始化程序的替代方法。 这会让我从一个基本的 C# 问题中错过“太明显而无法打扰”的代码。修改后的代码现在会做他想做的事,不是吗? 现在的问题是每个派生类都需要调用初始化程序。我认为你想要的是默认运行初始化,但如果有必要有办法阻止它。这将完成这项工作,但不是 IMO 的最佳解决方案。【参考方案4】:

如果您确实需要首先运行您的构造函数,那么我建议使用受保护的 Initialize 方法,该方法由您的构造函数调用并执行初始化类的实际工作。您需要提供一个允许跳过初始化的替代构造函数。

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();
    

【讨论】:

【参考方案5】:

您必须在派生类构造函数的主体之前调用基类构造函数。

class Derived : Base

  public Derived(string someParams)
    : base("Blah " + someParams)
  

  


【讨论】:

这可能是这个简单案例的最佳解决方案,但如果构造参数要复杂得多,它会很快变得丑陋。 确实如此,尽管您也可以在静态方法中构造参数并将结果传递给基类构造函数。我更喜欢这种方法。或者,由于这是 .NET,因此您可以从构造函数中删除内容并在 setter 中执行,这是序列化友好的。【参考方案6】:

构造函数需要注意的点:

· 构造函数不能是“虚拟的”。

· 他们不能被继承。

· 构造函数按继承顺序调用。

public Child(string a):base(a)

【讨论】:

【参考方案7】:

你不能。你可以先调用它:

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();
  

【讨论】:

既然 Base 构造函数应该做一些事情(可能是 sMessage 的一些事情),这段代码是如何解决他的问题的? 如果你使用钩子,你需要有办法避免调用默认的基础构造函数。请参阅我的答案,通过提供不运行初始化程序的构造函数来避免这种情况。 @wcm:我只是展示了实现 DotnetDude 需要的操作顺序的步骤。看起来他对 C# 的理解足够好,可以从这里更改参数并返回对象以满足他的实际需求。 @Dinah -- 如果没有默认构造函数,这甚至无法编译。如果添加调用 init() 的默认构造函数,则 init() 会被调用两次:一次在基构造函数中,一次在派生构造函数中。如果你使用钩子实现,你需要有一个不运行它的构造函数。

以上是关于在 C# 中调用基本构造函数 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

C# - 在一些计算后从另一个构造函数调用构造函数[重复]

在 C# 中,您需要调用基本构造函数吗?

在 C# 中的类构造函数中调用异步方法 [重复]

c#构造函数外的基本关键字[重复]

如何防止 C# 中的继承者调用基本构造函数?

C# base() 构造函数顺序[重复]