Modifying parameter values before sending to Base constructor

11,911

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.

Share:
11,911
Ian P
Author by

Ian P

Computer nerd.

Updated on June 04, 2022

Comments

  • Ian P
    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 an int,) 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
    Reed Copsey over 14 years
    You can't create "value" via logic in the DerivedClass constructor, though, because base(...) is run first.
  • JaredPar
    JaredPar over 14 years
    @Reed, yeah that was a typo. Meant to put (InputType)i. Fixed
  • Reed Copsey
    Reed Copsey over 14 years
    Yes, you can cast. But he was asking for a way to use logic to create value, which you can't do.
  • Ian P
    Ian P over 14 years
    See edit, I typed the comment on the wrong line.. Meant to type it below the base constructor call.
  • JaredPar
    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.
    Ed S. over 14 years
    OK, I see that others have suggested to you that you can modify the value before sending it to the base constructor.
  • Omri Gazitt
    Omri Gazitt about 12 years
    Pavel, is there any way to do this if the base class takes more than one constructor argument?
  • Pavel Minaev
    Pavel Minaev about 12 years
    You 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
    Omri Gazitt about 12 years
    Thanks 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