Reputation: 82301
I have a default constructor in my class that initializes stuff.
I don't want copy/paste that into another constructor I have that needs to have :base(otherStuff)
on it. I am guessing I will have to (or abstract it out to a method or some such thing).
But I am wondering, why are both not supported?
(Sometimes when I want something that the language does not support it means I am doing something wrong.)
Example:
public class SomeClass : SomeBase
{
public SomeClass()
{
// Init a lot of lists and stuff
}
public SomeClass(OtherThings otherThings): base(otherThings)
// :this() <----- This is not legal syntax
{
// Do stuff with otherThings
}
}
Upvotes: 5
Views: 142
Reputation: 20909
I think the reasoning for this is the fact that base constructor is always executed before executing any constructor of your type which means that deriving from existing construtor c1()
of your type already embedds deriving from base construtor b1()
- and you obviously can't derive from 2 different base constrructors.
It's a bit confusing as this()
constructor actually derives from base()
constructor implicitly, so your code is equivalent to :
public class SomeClass : SomeBase
{
public SomeClass(): **base()**
{
// Init a lot of lists and stuff
}
public SomeClass(OtherThings otherThings): base(otherThings)
// :this() <----- This is not legal syntax
{
// Do stuff with otherThings
}
}
now it is obvious that you can't have SomeClass(OtherThings otherThings): base(otherThings):this()
as compiler would not be able to execute 2 base constructors (base(otherThings)
and base()
).
UPD: Thinking of why it is prohibited to depend on 2 constructors I came into this example:
public class SomeBase {
public SomeBase(){}
public SomeBase(OtherThings otherThings):this(){}
}
public class SomeClass : SomeBase
{
public SomeClass(): base()
{
// Init a lot of lists and stuff
}
public SomeClass(OtherThings otherThings): base(otherThings)
// :this() <----- This is not legal syntax
{
// Do stuff with otherThings
}
}
Allowing to have SomeClass(OtherThings otherThings):base(otherThings):this()
would result in SomeBase()
being executed twice which is ridiculous and unexpected (once for :base(otherThings)
and the other time for SomeClass(): base()
which both depend on parameterless constructor base()
).
Upvotes: 3
Reputation: 139
There is a pretty solid reasoning behind this - your base class shall be fully initialized before you start doing constructor stuff in derived type.
From your example it looks like you have two separate ways of initializing one class - perhaps yous shall consider changing your architecture for simpler one?
If that is not possible you might indeed like to use initialization method or chain your constructors like:
class A
{
// no longer needed
//public A()
//{
//}
public A(SomeStuff stuff)
{
if (stuff != null)
{
// init stuff
}
}
}
class B : A
{
public B() : this(null)
{
}
public B(SomeStuff stuff) : base(stuff)
{
if (stuff != null)
{
// init stuff more
}
}
}
In this situation your construction chain is proper - this.default() -> this.specialized(null) -> base.specialized(null)
.
Of course, if A()
is doing anything important you might keep it and just call from A(SomeStuff)
.
Upvotes: 0
Reputation: 44439
Consider this situation:
class Base
{
public Base() { }
public Base(string s) { }
}
class Derived : Base
{
public Derived() : base("default") { }
public Derived() : base()
: this() { }
}
It should be clear that this is guaranteed to cause trouble if it were allowed. Which base constructor would end up getting invoked?
Solutions have already been provided: extract it out to a method.
Upvotes: 2
Reputation: 48139
I don't know exactly why, but I had similar in the past and had to resort to something like...
public class SomeClass : SomeBase
{
public SomeClass()
{
// Init a lot of lists and stuff
CommonStuff();
}
public SomeClass(OtherThings otherThings): base(otherThings)
{
CommonStuff();
// Do stuff with otherThings
}
private void CommonStuff()
{
// init common between both
}
}
Upvotes: 2