简体   繁体   English

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

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

Firstly, sorry for my English.首先,对不起我的英语。 I hope i can explain my problem.我希望我能解释我的问题。

I have class like this我有这样的课

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

Also i have class like this我也有这样的课

public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
    private Car _Car;
    public CarStringCommandExecutor(Car car)
    {
        _Car = car;
        // this Constructor gives me an error.
    }
    public void ExecuteCommand(string commandObject)
    {
        if (string.IsNullOrEmpty(commandObject))
            throw new Exception("Komutlarda hata var.");

        char[] commands = commandObject.ToCharArray();

        for (int i = 0; i < commands.Length; i++)
        {
            switch (commands[i])
            {
                case 'L':
                    break;
                case 'R':
                    break;
                case 'M':
                    break;
                default:
                    throw new Exception("Komutlarda hata var.");
            }
        }
    }
}

Error message:错误信息: 错误

What's the reason and how can i fix it?是什么原因,我该如何解决? Thanks.谢谢。

One of the things that isn't immediately apparent, thanks to "compiler magic", about a C# class is that every class has a constructor由于“编译器魔法”,关于 C# 类的一件事不是立即显而易见的,就是每个类都有一个构造函数

It needs to be this way because it's a rule that object construction happens in a tree;必须这样,因为对象构造发生在树中是一个规则; you construct some class Z which inherits from Y which inherits from X which inherits from object , and Z 's cosntructor invokes Y 's invokes X 's invokes object 's, then they finish, in order of object, X, Y, Z and you have your nicely constructed thing - every constructor on the way up the tree had its chance to do its init and ready the object for use (the part of it that each constructor was responsible for)您构造了一些继承自YZ ,该类继承自X继承自object ,并且Z的构造函数调用Y的调用X的调用object的,然后它们按object, X, Y, Z顺序完成并且你有你精心构建的东西 - 树上的每个构造函数都有机会进行初始化并准备好使用对象(每个构造函数负责的部分)

Even classes that don't seem to have constructors, have constructors :即使类似乎没有构造函数,也有构造函数

class X { 

}

If you don't provide a constructor, C# provides one for you.如果您不提供构造函数,C# 会为您提供一个。 You never see it in your source code;你永远不会在你的源代码中看到它; just imagine that in between reading the file and compiling it, the compiler inserts it for you.想象一下,在读取文件和编译文件之间,编译器会为您插入它。 It takes no parameters, has no code, and does nothing other than call its base:它没有参数,没有代码,除了调用它的基类之外什么都不做:

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

If you provide a constructor but don't write the base... bit, C# puts base() in for you behind the scenes (and it always calls the no-argument base() ) but critically it doesn't provide an empty constructor if you provided one already如果您提供了一个构造函数但不编写base...位,C# 会在幕后为您放置base() (并且它总是调用无参数base() )但关键的是它不提供一个空的构造函数,如果你已经提供了一个

This means if you have a class like:这意味着如果你有一个类:

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

Your class X has a constructor, so C# won't provide the empty one, so now anything that tries to construct your class must provide a string message :你的类 X 有一个构造函数,所以 C# 不会提供空的,所以现在任何试图构造你的类的东西都必须提供一个string message

X x = new X("hello");

If you now inherit from X, you might do one of 3 things (with Y):如果您现在从 X 继承,您可能会执行以下 3 件事之一(使用 Y):

class Y:X{

}
  1. You don't add a constructor, C# adds one, but it just dumbly calls base() , which doesn't work because there is no constructor in X that takes no args:您没有添加构造函数,C# 会添加一个构造函数,但它只是愚蠢地调用base() ,这不起作用,因为 X 中没有不带参数的构造函数:

     class Y:X{ Y():base() { } }
  2. You add a constructor but leave off the base bit.您添加了一个构造函数,但保留了base位。 C# adds it, again just literally as base() - this also doesn't work for the same reason C# 再次添加它,就像base() ——出于同样的原因,这也不起作用

    class Y:X{ Y(int myArg) //c# adds base() in here for you { ... } }
  3. You add a constructor that includes a call to base and because you know your base class only has a constructor with a string arg, you pass one:您添加了一个包含对base调用的构造函数,并且因为您知道您的基类只有一个带有字符串 arg 的构造函数,所以您传递了一个:

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

So you're in scenario 2, and you either need to:所以你在场景 2 中,你要么需要:

  • Add a no-arg constructor to the base class so that c#'s auto-inserted stuff works or,向基类添加一个无参数构造函数,以便 c# 的自动插入的东西起作用,或者,
  • Add a call to base(...) with a suitable argument, to stop C# from putting a base() in使用合适的参数添加对base(...)的调用,以阻止 C# 将base()放入

I've left out access modifiers from code in this answer for clarity of demonstrating the essential point.为了清楚地展示要点,我在此答案中的代码中省略了访问修饰符。 Whether a constructor is accessible or not can also have a bearing on all this, but I deemed it out of scope构造函数是否可访问也与所有这些有关,但我认为它超出了范围

Since the only constructor in CarCommandExecutorBase is defined like this由于CarCommandExecutorBase唯一的构造CarCommandExecutorBase是这样定义的

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

you have to pass an ICarCommand when creating an instance of CarCommandExecutorBase .创建ICarCommand的实例时,您必须传递CarCommandExecutorBase

You have to provide an ICarCommand through the constructor of CarStringCommandExecutor , because when instantiating a derived type the base constructor(s) also get called.您必须通过ICarCommand的构造函数提供CarStringCommandExecutor ,因为在实例化派生类型时,也会调用基本构造函数。

See this answer for more detailed information about this: https://stackoverflow.com/a/1882778/8450550有关更多详细信息,请参阅此答案: https : //stackoverflow.com/a/1882778/8450550

You could do something like this to solve this error:您可以执行以下操作来解决此错误:

public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
    ...

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

or maybe this或者这个

public class CarStringCommandExecutor : CarCommandExecutorBase, IStringCommand
{
    ...

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

or you add another constructor to CarCommandExecutorBase which expects no arguments:或者您向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()
    {

    }
}

Which solution works best in your case is up to you.哪种解决方案最适合您的情况取决于您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM