在 C# 中调用重写的构造函数和基构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/335286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:41:09  来源:igfitidea点击:

Calling Overridden Constructor and Base Constructor in C#

c#constructor

提问by reilly

I have two classes, Foo and Bar, that have constructors like this:

我有两个类,Foo 和 Bar,它们有这样的构造函数:

class Foo
{
    Foo()
    {
      // do some stuff
    }

    Foo(int arg)
    {
      // do some other stuff
    }
}

class Bar : Foo
{
    Bar() : base()
    {
      // some third thing
    }
}

Now I want to introduce a constructor for Bar that takes an int, but I want the stuff that happens in Bar() to run as wellas the stuff from Foo(int). Something like this:

现在我想为 Bar 引入一个接受 int 的构造函数,但我希望 Bar() 中发生的事情以及Foo(int)中发生的事情都能运行。像这样的东西:

Bar(int arg) : Bar(), base(arg)
{
  // some fourth thing
}

Is there any way to do this in C#? The best I have so far is putting the work done by Bar() into a function, that also gets called by Bar(int), but this is pretty inelegant.

有没有办法在 C# 中做到这一点?到目前为止,我所做的最好的工作是将 Bar() 完成的工作放入一个函数中,该函数也由 Bar(int) 调用,但这非常不雅。

采纳答案by Curt Hagenlocher

No, this isn't possible. If you use Reflector to examine the IL that's generated for each constructor, you'll see why -- you'd end up calling both of the constructors for the base class. In theory, the compiler could construct hidden methods to accomplish what you want, but there really isn't any advantage over you doing the same thing explicitly.

不,这是不可能的。如果您使用 Reflector 检查为每个构造函数生成的 IL,您就会明白为什么——您最终会调用基类的两个构造函数。理论上,编译器可以构造隐藏方法来完成您想要的操作,但与您显式执行相同操作相比,确实没有任何优势。

回答by Jim Anderson

Can't you have the Bar constructor that takes an int invoke the parameterless constructor?

你不能让带 int 的 Bar 构造函数调用无参数构造函数吗?

回答by g .

Can you put the stuff from Bar() in Bar(int) and call Bar(int) with Bar() with a default value? Then Bar(int) can call the base constructor.

你能把 Bar() 中的东西放在 Bar(int) 中,然后用 Bar() 调用 Bar(int) 并使用默认值吗?然后 Bar(int) 可以调用基本构造函数。

class Bar : Foo
{
    Bar() : this(0)
    {
    }

    Bar(int arg) : base(arg)
    {
    }
}

That doesn't exactly answer your question, but depending on your scenario might be a workable solution.

这并不能完全回答您的问题,但根据您的情况可能是一个可行的解决方案。

回答by Ilya Ryzhenkov

I would re-chain constructors, so they are called like

我会重新链接构造函数,所以它们被称为

Bar() : this(0) 
Bar(int) : Foo(int) initializes Bar
Foo(int) initializes Foo
Foo() : this(0) 

This is suitable, if parameterless constructors are assuming some kind of default value for int parameter of other constructor. If constructors are unrelated, you probably doing something wrong with your type, or maybe we need more information about what are you trying to achieve.

如果无参数构造函数为其他构造函数的 int 参数假定某种默认值,这是合适的。如果构造函数不相关,则您的类型可能有问题,或者我们可能需要有关您要实现的目标的更多信息。

回答by Charles Bretana

This is only thing I can think of...

这是我唯一能想到的...

 public class Foo
{
    public Foo()
    {
    }
    public Foo(int? arg): this()
    {
    }

}
public class Bar : Foo
{
    private int x;
    public Bar(): this(new int?()) // edited to fix type ambiguity
    {
        // stuff that only runs for paramerless ctor
    }
    public Bar(int? arg)
        : base(arg)
    {
        if (arg.HasValue)
        {
            // Do stuff for both parameterless and parameterized ctor
        }
        // Do other stuff for only parameterized ctor
    }
}

回答by NerdFury

I would recommend changing your constructor chain to go from least specific to most specific.

我建议将您的构造函数链更改为从最不具体到最具体。

class Foo
{
    Foo()
    {
      // do some stuff
    }

    Foo(int arg): this()
    {
      // do some other stuff
    }
}

class Bar : Foo
{
    Bar() : Bar(0)
    {
      // some third thing
    }

    Bar(int arg): base(arg)
    {
      // something
    }
}

Any creation of the Bar object will now call all 4 constructors. Constructor chaining should provide default values to more specific constructors, not the other way around. You should really look at what you are trying to accomplish and make sure what you are doing makes sense. Curt is right that there are technical reasons you can't do this, but there are also logical reasons why you shouldn't.

Bar 对象的任何创建现在都将调用所有 4 个构造函数。构造函数链应该为更具体的构造函数提供默认值,而不是相反。你真的应该看看你想要完成什么,并确保你正在做的事情有意义。Curt 是对的,你不能这样做有技术原因,但也有你不应该这样做的合乎逻辑的原因。

回答by CSharpAtl

can you take the initialization code for Bar() and make it a method and call it from both constructors, and have the new constructor just call base(arg)?

你能把 Bar() 的初始化代码变成一个方法并从两个构造函数中调用它,让新的构造函数只调用 base(arg) 吗?

回答by Moch Yusup

You can use this code:

您可以使用此代码:

public Foo
{
    public Foo()
    {
        this.InitializeObject();
    }

    public Foo(int arg) : this()
    {
        // do something with Foo's arg
    }

    protected virtual void InitializeObject()
    {
        // initialize object Foo
    }
}

public Bar : Foo
{
    public Bar : base() { }

    public Bar(int arg) : base(arg)
    {
       // do something with Bar's arg
    }

    protected override void InitializeObject()
    {
       // initialize object Bar

       base.InitializeObject();
    }
}

Just override the InitializeObject()method just like in the code above, and put all your code that you want to put in parameter-less constructor there. And finally call base.InitializeObject()at the end of the code.

只需InitializeObject()像上面的代码一样覆盖该方法,并将所有要放入无参数构造函数的代码放在那里。最后base.InitializeObject()在代码末尾调用。

Hope this is useful.

希望这是有用的。