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

Calling Overridden Constructor and Base Constructor in C#

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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)中的事情运行起来。像这样:

1
2
3
4
Bar(int arg) : Bar(), base(arg)
{
  // some fourth thing
}

用C语言有什么方法可以做到这一点吗?到目前为止,我所做的最好的工作是将bar()所做的工作放入一个函数中,这个函数也由bar(int)调用,但这非常不雅。


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

1
2
3
4
Bar() : this(0)
Bar(int) : Foo(int) initializes Bar
Foo(int) initializes Foo
Foo() : this(0)

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


不,这不可能。如果您使用Reflector来检查为每个构造函数生成的IL,您将看到为什么——您最终会为基类调用这两个构造函数。从理论上讲,编译器可以构造隐藏的方法来完成您想要的工作,但实际上没有任何优势比您显式地执行相同的工作更好。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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是对的,有一些技术原因你不能这样做,但也有一些逻辑原因你不应该这样做。


这是我唯一能想到的…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 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
    }
}


您能否获取bar()的初始化代码并使其成为一个方法并从两个构造函数调用它,让新的构造函数只调用base(arg)?


你能把bar()中的内容放到bar(int)中吗?能把bar()中的内容放到call bar(int)中吗?然后bar(int)可以调用基构造函数。

1
2
3
4
5
6
7
8
9
10
class Bar : Foo
{
    Bar() : this(0)
    {
    }

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

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


不能让接受int的bar构造函数调用无参数构造函数吗?


您可以使用此代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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()

希望这是有用的。