C# - 当我尝试创建构造函数时,出现 CS7036 错误

C# - When i try to create constructor, i get CS7036 error

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

我有class这样的

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

我也有class这样的

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

    }
}

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

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

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

需要这样,因为对象构造发生在树中是规则;你构造了一些 class Z 继承自 Y 继承自 X 继承自 objectZ 的构造函数调用 Y 的调用 X 的调用 object 的,然后它们按 object, X, Y, Z 的顺序完成,你就得到了你精心构造的东西——树上的每个构造函数有机会执行它的初始化并准备好对象以供使用(每个构造函数负责的部分)

甚至 classes 似乎没有构造函数,但有构造函数:

class X { 

}

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

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

如果您提供构造函数但不写入 base... 位,C# 会在幕后为您放入 base()(它总是调用无参数 base() ) 但重要的是 如果您已经提供一个构造函数,它不会提供一个空的构造函数

这意味着如果您 class 喜欢:

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

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

X x = new X("hello");

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

class Y:X{

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

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

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

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

所以你在场景 2 中,你需要:

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

为了清楚地展示要点,我在这个答案的代码中省略了访问修饰符。构造函数是否可访问也可能与所有这些有关,但我认为它超出了范围

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

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

在创建 CarCommandExecutorBase.

的实例时,您 必须 传递 ICarCommand

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

有关此问题的更多详细信息,请参阅此答案:

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

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

    }
}

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