Modifying parameter values before sending to Base constructor
Solution 1
I expect you could call static methods in the parameter list of the base class constructor.
public class DerivedClass : BaseClass
{
public DerivedClass(int i)
: base(ChooseInputType(i))
{
}
private static InputType ChooseInputType(int i)
{
// Logic
return InputType.Number;
}
}
Solution 2
You can use a static method to compute a value to pass to the base constructor.
public class DerivedClass :
BaseClass
{
public
DerivedClass(int i) :
base(ComputedValue(i))
{
}
public static InputType
ComputedValue(int i)
{
return InputType.Number; // or any other computation you want here
}
}
Solution 3
Yes. It's fine to use normal expressions, which don't access the instance, in order to manipulate the value. For instance
public DerivedClass(int i)
: base((InputType)i)
{
}
Solution 4
You can create a static method on derived class and put your logic there:
public enum InputType {
Number = 1,
String = 2,
Date = 3
}
public class BaseClass {
public BaseClass(InputType t) {
// Logic
}
}
public class DerivedClass : BaseClass {
public DerivedClass(int i)
: base(GetInputType(i)) {
// Is it possible to set "value" here?
// Logic
}
private static InputType GetInputType(Int32 parameter) {
// Do something with parameter
// and return an InputType
return (InputType)Enum.Parse(typeof(InputType), parameter);
}
}
Solution 5
One hack to put arbitrary logic in base()
clause without introducing a separate static method is to use a lambda or anonymous delegate. The expression inside base()
is in scope of all constructor parameters, so you can freely use them inside the lambda. E.g. (let's say this is C# 2.0, so there's no LINQ to write a single-liner for the same thing):
class Base
{
public Base(int[] xs) {}
}
class Derived : Base
{
public Derived(int first, int last)
: base(
((Func<int[]>)delegate
{
List<int> xs = new List<int>();
for (int x = first; x < last; ++x)
{
xs.Add(x);
}
return xs.ToArray();
})())
{
}
}
However, I would strongly advise against using this in practice, because from readability point of view this is really horrible. With a static method you'll need to explicitly pass constructor arguments to it, but it's not like you normally have more than 3-4 of those.
Comments
-
Ian P about 2 years
The title may be a bit ambiguous, but I couldn't think of a better way to word this.
I realize that I can not call a derived constructor prior to calling a base constructor, but can I somehow modify/create parameters values prior to passing them to the base?
For example,
public enum InputType { Number = 1, String = 2, Date = 3 } public class BaseClass { public BaseClass(InputType t) { // Logic } } public class DerivedClass : BaseClass { public DerivedClass(int i) : base(value) // Can I do something to infer what value should be here? { // Logic } }
If I have a derived class that can infer the value required for the base constructor (in this example,
InputType.Number
would be valid for anint
,) is there a way to modify and/or create values that are passed to the base constructor prior to the derived constructor executing? -
Reed Copsey over 14 yearsYou can't create "value" via logic in the DerivedClass constructor, though, because base(...) is run first.
-
JaredPar over 14 years@Reed, yeah that was a typo. Meant to put (InputType)i. Fixed
-
Reed Copsey over 14 yearsYes, you can cast. But he was asking for a way to use logic to create value, which you can't do.
-
Ian P over 14 yearsSee edit, I typed the comment on the wrong line.. Meant to type it below the base constructor call.
-
JaredPar over 14 years@Reed, I'm still not entirely sure where value is coming from in the OP's question. But it is possible to create new values which can be passed to the base class constructors (via static methods for instance). It just can't be done using instance methods on DerivedClass.
-
Ed S. over 14 yearsOK, I see that others have suggested to you that you can modify the value before sending it to the base constructor.
-
Omri Gazitt about 12 yearsPavel, is there any way to do this if the base class takes more than one constructor argument?
-
Pavel Minaev about 12 yearsYou can have a separate lambda for every argument, but you won't be able to share variables between those lambdas (except for constructor arguments).
-
Omri Gazitt about 12 yearsThanks Pavel - that's exactly the issue I'm trying to resolve.. (sharing variables between lambdas). Basically I want to encapsulate some logic that does some computation and returns three different (but related) fields, each of which will initialize a distinct parameter for the base class's constructor. I ended up working around this by going back to the static method approach (more readable as you said), returning a struct, and calling the static method once for each parameter. It's hacky, but worked, since for my scenario there aren't any side effects between invocations of static method