【问题标题】:C# - Making all derived classes call the base class constructorC# - 使所有派生类调用基类构造函数
【发布时间】:2014-11-27 07:02:03
【问题描述】:

我有一个基类 Character,它有几个派生自它的类。基类有各种字段和方法。

我的所有派生类都使用相同的基类构造函数,但如果我不在派生类中重新定义构造函数,我会收到错误:

错误:类“子类”不包含采用此数量参数的构造函数

我不想在每个派生类中重新定义构造函数,因为如果构造函数发生更改,我必须在每个单独的类中更改它,请原谅任何误解,这违背了只编写一次代码的想法?

【问题讨论】:

  • 你在构造函数中做了什么类型的工作?一般来说,除了实例化成员之外,不应该在构造函数中完成任何其他工作。
  • 是的,只是实例化成员。基类包含所有派生类使用的 5 个字段,所以我只是将这些作为构造函数参数传递并设置基类字段。
  • 有点相关但不重复:stackoverflow.com/q/12051/492

标签: c# inheritance constructor


【解决方案1】:

您可以使用以下语法从派生的类中调用基类构造函数:

public DerivedClass() : base() {
    // Do additional work here otherwise you can leave it empty
}

这将首先调用基本构造函数,然后在派生构造函数中执行任何附加语句(如果有)。

请注意,如果基础构造函数接受参数,您可以这样做:

public DerivedClass(int parameter1, string parameter2) 
    : base(parameter1, parameter2) {
    // DerivedClass parameter types have to match base class types
    // Do additional work here otherwise you can leave it empty
}

您可以在以下页面中找到有关构造函数的更多信息:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-constructors

在派生类中,如果未使用base 关键字显式调用基类构造函数,则隐式调用默认构造函数(如果有)。

【讨论】:

  • @user491704 很高兴为您服务
  • public DerivedClass() : base() {},冗余基础构造函数调用
  • 为了使@macio.Jun 的评论更加明确:如果非静态构造函数重载(在class 中)既不包含: base(...) 也不包含:this (...),则调用零参数隐含基类构造函数。因此,如果没有明确提及链接,则与编写: base() 相同。此外,如果没有为非静态 class 编写非静态构造函数,编译器将生成一个空的零参数构造函数,该构造函数链接 : base()
【解决方案2】:

确实必须重新声明构造函数,因为它们实际上没有被继承。如果您认为构造函数在某些方面有点像静态方法,这是有道理的。

特别是,您不会希望自动继承所有构造函数 - 毕竟,这意味着 每个 类都有一个无参数构造函数,如 @987654321 @ 本身就可以。

如果您只想调用基类构造函数,则无需在构造函数的主体中编写任何代码 - 只需按照 Waleed 的帖子将参数传递给基类即可。

如果您的基类开始需要更多信息,那么您很自然应该更改所有派生类——实际上是任何调用这些类的构造函数的东西——因为它们必须提供信息。我知道这看起来很痛苦,但这只是构造函数所做的自然结果。

【讨论】:

    【解决方案3】:

    一种替代方法可能是依赖依赖注入容器来初始化您的对象,这样对基类的引用(可能是对基构造函数或其他初始化方法的调用)将“外部化”到DI 容器。

    我不知道这对你的情况是否有意义

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,我通过用这样的工厂方法替换我的构造函数来解决它:

      A 是父类。

      public static T getChild<T>(int number) where T:A, new()
      {
          T child = new T();
          T._number = number;
          return child;
      
      }
      

      你可以创建一个子类

      Child b = A.getChild&lt;Child&gt;(2);

      【讨论】:

      • 为什么这不是这个问题的答案?它替换了每个子类中的空构造函数public Child(int number) : base(number){}
      • 在@Ben 编辑答案之前,它就像一个“我遇到了同样的问题”的帖子。我恭敬地撤回我的第一条评论。
      • 啊,好吧,你是对的。听起来确实如此。谢谢你的评论。
      • @HashemQolami:你必须彻底阅读“我有同样的问题”的答案,看看他们是否也提供了解决方案。
      猜你喜欢
      • 2015-08-18
      • 2016-07-19
      • 2018-07-21
      • 2018-07-16
      • 2020-11-28
      • 2011-05-03
      • 2020-09-22
      • 1970-01-01
      相关资源
      最近更新 更多