51

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

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

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

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

现在我想为 Bar 引入一个采用 int 的构造函数,但我希望 Bar() 中发生的内容与 Foo(int) 中的内容一样运行。像这样的东西:

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

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

4

8 回答 8

32

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

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

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

于 2008-12-02T20:29:44.440 回答
24

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

于 2008-12-02T20:29:00.900 回答
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 是对的,有技术原因你不能这样做,但也有逻辑原因你不应该这样做。

于 2008-12-02T20:33:22.763 回答
4

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

 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
    }
}
于 2008-12-02T20:32:48.723 回答
1

难道你不能让接受 int 的 Bar 构造函数调用无参数构造函数吗?

于 2008-12-02T20:27:59.420 回答
1

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

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

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

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

于 2008-12-02T20:29:15.437 回答
1

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

于 2008-12-02T20:38:29.600 回答
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()最后在代码末尾调用。

希望这是有用的。

于 2013-04-30T02:45:41.113 回答