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(); } } |
就像上面的代码一样,只需重写
希望这是有用的。