Reputation: 475
(Simplified) Scenario:
public class BaseClass
{
public int BaseClassInt {get; set;}
public BaseClass(int pBaseClassInt)
{ this.BaseClassInt = pBaseClassInt; }
}
public class DerivedClass : BaseClass
{
public int DerivedClassInt {get; set;}
public DerivedClass (int pBaseClassInt, int pDerivedClassInt) : base(pBaseClassInt)
{ this.DerivedClassInt = pDerivedClassInt; }
}
If I want to instantiate a DerivedClass-object I have to pass all arguments required to create a BaseClass-object and a DerivedClass-object. Also for every BaseClass-constructor I have to (at least should in my concrete case) provide a constructor with the same arguments in the derived class, plus arguments for the derived class properties. Then, if I change or delete a constructor in the base class I have to change or delete the corresponding contructor in the derived class(es).
I wonder if it is possible to use a constructor for the derived class which accepts a base class-object as an argument:
public DerivedClass(BaseClass pBaseClassObejct, int pDerivedClassInt)
{
// to make clear what I intend to do - looks silly of course
this = (DerivedClass)pBaseClassObject;
this.DerivedClassInt = pDerivedClassInt;
}
This could be called:
DerivedClass DerivedClassObject = new DerivedClass((new BaseClass(1),2);
If constructors in the base class would change, I wouldn´t have to mind it for the derived class. Is there any way to achieve this?
Upvotes: 2
Views: 5195
Reputation: 583
This might be help!
Solution A: Create Inherit instead of base!
public static class Test
{
public static T Foo<T>(string text, int num) where T : BaseClass
{
T @base = (T)Activator.CreateInstance(typeof(T), new object[] { text, num });
//...
return @base;
}
public static void Main()
{
InheritClass inherit = Foo<InheritClass>("Hi there", 10);
}
}
Solution B: Copy base to inherit
public static class Test
{
public static TInherit As<TBase, TInherit>(this TBase @this) where TInherit : TBase
{
var type = typeof(TInherit);
var instance = Activator.CreateInstance(type);
foreach (var property in type.GetProperties())
if (property.CanWrite)
property.SetValue(instance, property.GetValue(@this, null), null);
return (TInherit)instance;
}
public static BaseClass Foo(string text, int num)
{
BaseClass @base = new BaseClass(text, num);
//...
return @base;
}
public static void Main()
{
InheritClass inherit = Foo("Hi there", 10).As<BaseClass, InheritClass>();
}
}
Notes: you can have simple 'As()' found here, but i prefer mine (where Inherit : TBase), where it's more safe and support converting base to inherit of inherit class.
Upvotes: 0
Reputation: 61982
This feature is not available. I think what you want is a little like this:
Suppose C# had a keyword allbaseargs
and allowed code like this:
public class DerivedClass : BaseClass
{
public int DerivedClassInt { get; set; }
public DerivedClass (allbaseargs, int pDerivedClassInt)
: base(allbaseargs)
{
DerivedClassInt = pDerivedClassInt;
}
}
Then this could only work if BaseClass
had only one (accessible) instance constructor.
The compiler should then examine the sole base constructor and substitute the magical word allbaseargs
with the parameters of that constructor.
However, C# does not have this feature, and you would have to hand-code everything, which includes changeing all : base(...)
calls of all derived classes when the constructor signature changes.
It is allowed to have the signature:
public DerivedClass(BaseClass pBaseClassObejct, int DerivedClassInt)
like you suggest, but you would not be able to chain the : base(...)
easily. You would have to equip BaseClass
with a construtor that took another instance in and copied all "state" (all instance properties and fields and such) from that other instance to "this
". I do not recommend that solution.
Upvotes: 1
Reputation: 19121
Think about this line for a moment:
this = (DerivedClass) pBaseClassObject;
Let's ignore the fact that you cant set this
directly that way, and focus on the rest.
Imagine Giraffe
and Elephant
are both implementations of AfricanAnimal:
// By extension, ellie is also an AfricanAnimal
Elephant ellie = new Elephant();
// assume ellie is passed in as a param here (she can
// be, because she is an AfricanAnimal after all!):
public Giraffe(AfricanAnimal ellie)
{
this = (Giraffe) ellie; // Can't do this!
}
You can't (and would not want to) force ellie into being a giraffe, because a giraffe may have properties etc. that ellie lacks, and ellie may have properties that Giraffes don't have. Yet, using an AfricanAnimal
as your parameter type there, would allow for just that.
Note: You could write that code and pass a Giraffe in, and all would be fine, but then again, that makes little sense; then you might as well use the Giraffe type as the parameter.
If you replace this
with an instance variable, you would be able to compile with something like the following...
public Giraffe(AfricanAnimal ellie)
{
this.varOfTypeGiraffe = (Giraffe) ellie;
}
... but as soon as you run it with an Elephant
as a a prameter, you will get an exception similar to:
InvalidCastException: Unable to cast object of type 'Elephant' to type 'Giraffe'.
Upvotes: 3
Reputation: 3149
No, that is not possible and should not be, because it doesn't make sense.
If it was possible and you deleted/changed the base class constructor, you would still need to change the code which creates the base class object that you would use as an argument to the derived class constructor.
Also, not all base classes are concrete. You would not be able to create an abstract base class, right?
Upvotes: 2
Reputation: 437534
TL;DR: This is a bad idea. Don't even try.
You cannot make a base constructor run from inside the body of any derived method (including the derived constructor). Even if you could, a base instance would not have retained any information about which constructor was used to instantiate it so there would be no way to know which base constructor should be called.
The above refers to the general case where a base constructor can potentially modify application state not directly related to the base class (e.g. by changing the value of static fields somewhere). You could use reflection to copy property values from a base instance to the derived instance being created, but this is practically unworkable because
abstract
, or if creating one has side effects?Upvotes: 2