【问题标题】:C# - When i try to create constructor, i get CS7036 errorC# - 当我尝试创建构造函数时,出现 CS7036 错误
【发布时间】:2021-12-03 22:29:27
【问题描述】:

首先,对不起我的英语。我希望我能解释我的问题。

我有这样的课

public class CarCommandExecutorBase
{
    protected readonly ICarCommand CarCommand;
    public CarCommandExecutorBase(ICarCommand carCommand)
    {
        CarCommand = carCommand;
    }
}

我也有这样的课

public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
    public CarStringCommandExecutor(Car car)
    {
        // this Constructor gives me an error.
    }
    public void ExecuteCommand(string commandObject)
    {

    }
}

错误信息: [![错误][1]][1]

这是什么原因,我该如何解决?谢谢。

【问题讨论】:

  • 您需要在此构造函数中添加: base (……。您的基类具有构造函数,您也需要将其作为参数传递
  • 或者添加一个空的构造函数到你的 CarCommandExecutorBase

标签: c# .net oop constructor


【解决方案1】:

由于CarCommandExecutorBase 中唯一的构造函数是这样定义的

public CarCommandExecutorBase(ICarCommand carCommand)
{
    CarCommand = carCommand;
}

必须在创建CarCommandExecutorBase 的实例时传递ICarCommand

您必须通过CarStringCommandExecutor 的构造函数提供ICarCommand,因为在实例化派生类型时,基构造函数也会被调用。

有关此问题的更多详细信息,请参阅此答案:https://stackoverflow.com/a/1882778/8450550

你可以这样做来解决这个错误:

public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
    ...

    public CarStringCommandExecutor(Car car, ICarCommand carCommand)
        : base(carCommand) // base() points to the constructor of the base class
    {
        ...
    }

或者这个

public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
    ...

    public CarStringCommandExecutor(Car car)
        : base(null) // passing null but be aware of NullReferenceExceptions
    {
        ...
    }

或者你添加另一个构造函数到CarCommandExecutorBase,它不需要参数:

public class CarCommandExecutorBase
{
    protected readonly ICarCommand CarCommand;
    public CarCommandExecutorBase(ICarCommand carCommand)
    {
        CarCommand = carCommand;
    }

    // mark this constructor as protected, so only deriving types can call it
    protected CarCommandExecutorBase()
    {

    }
}

哪种解决方案最适合您的情况取决于您。

【讨论】:

    【解决方案2】:

    由于“编译器魔法”,关于 C# 类的其中一件事不是很明显,每个类都有一个构造函数

    之所以需要这样,是因为对象构造发生在树中是一个规则;你构造了一些类Z,它继承自Y,它继承自X,它继承自object,并且Z的cosntructor调用Y的调用X的调用object' s,然后它们按object, X, Y, Z 的顺序完成,并且您拥有构造良好的东西-树上的每个构造函数都有机会进行初始化并准备好对象以供使用(每个构造函数的一部分)负责)

    即使是看起来没有构造函数的类,也有构造函数

    class X { 
    
    }
    

    如果您不提供构造函数,C# 会为您提供一个。您永远不会在源代码中看到它;想象一下,在读取文件和编译它之间,编译器会为你插入它。它没有参数,没有代码,除了调用它的基类之外什么都不做:

    class X { 
      X():base() { } //C# invisibly writes this for you
    }
    

    如果您提供构造函数但不编写 base... 位,C# 会在幕后为您提供 base()(它总是调用无参数 base()),但关键它没有'如果你已经提供了一个空的构造函数,则不提供一个

    这意味着如果你有这样的类:

    class X{
      X(string message){
        ...
      }
    }
    

    你的类 X 有一个构造函数,所以 C# 不会提供空的,所以现在任何试图构造你的类的东西都必须提供一个string message

    X x = new X("hello");
    

    如果您现在从 X 继承,您可能会做 3 件事之一(使用 Y):

    class Y:X{
    
    }
    
    1. 您不添加构造函数,C# 添加了一个,但它只是愚蠢地调用base(),这不起作用,因为 X 中没有不带 args 的构造函数:

       class Y:X{ 
         Y():base() { }
       }
      
    2. 您添加了一个构造函数,但省略了base 位。 C# 添加它,就像 base() 一样 - 这也因为同样的原因不起作用

      class Y:X{ 
         Y(int myArg)        //c# adds base() in here for you
         { 
           ...
         }
       }
      
    3. 您添加了一个包含对 base 的调用的构造函数,并且因为您知道您的基类只有一个带有字符串 arg 的构造函数,所以您传递了一个:

      class Y:X{ 
        Y(int myArg) : base("hello")
        { 
          ...
        }
      }
      

    所以您处于方案 2 中,您需要:

    • 向基类添加一个无参数构造函数,以便 c# 的自动插入的东西工作,或者,
    • 使用合适的参数添加对 base(...) 的调用,以阻止 C# 将 base() 放入

    为了清楚说明要点,我在此答案中的代码中省略了访问修饰符。构造函数是否可访问也会影响到这一切,但我认为它超出了范围

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      • 2020-03-03
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多