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

时间:2008-12-02 20:21:36

标签: c# constructor

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

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

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

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

现在我想介绍一个带有int的Bar的构造函数,但是我希望Bar()中发生的事情和一样运行作为来自Foo(int)的东西。像这样:

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

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

8 个答案:

答案 0 :(得分:32)

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

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

如果无参数构造函数为其他构造函数的int参数假定某种默认值,这是合适的。如果构造函数不相关,你可能会对你的类型做错了,或者我们需要更多关于你想要实现的内容的信息。

答案 1 :(得分:24)

不,这是不可能的。如果使用Reflector检查为每个构造函数生成的IL,您将看到原因 - 您最终会调用基类的两个构造函数。从理论上讲,编译器可以构造隐藏的方法来实现你想要的东西,但是你明确地做同样的事情没有任何优势。

答案 2 :(得分:13)

我建议您更改构造函数链,使其从最不具体到最具体。

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
    }
}

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

答案 3 :(得分:3)

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

 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
    }
}

答案 4 :(得分:1)

你不能让Bar构造函数接受一个int调用无参数构造函数吗?

答案 5 :(得分:1)

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

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

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

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

答案 6 :(得分:1)

你可以为Bar()获取初始化代码并使其成为一个方法并从两个构造函数中调用它,并让新的构造函数只调用base(arg)吗?

答案 7 :(得分:0)

您可以使用此代码:

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();
    }
}

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

希望这很有用。