views:

155

answers:

7

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?

Thanks for the info!

Ian

+1  A: 

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)
{
}
JaredPar
You can't create "value" via logic in the DerivedClass constructor, though, because base(...) is run first.
Reed Copsey
@Reed, yeah that was a typo. Meant to put (InputType)i. Fixed
JaredPar
Yes, you can cast. But he was asking for a way to use logic to create value, which you can't do.
Reed Copsey
@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.
JaredPar
A: 

No.

The base constructor is run prior to any logic in the DerivedClass constructor, so there is no way to inject logic.

You can, however, run the base class constructor, then set properties in the base class during the dervied class's constructor in order to change values.

Reed Copsey
A: 

You say

I realize that I can not call a derived constructor prior to calling a base constructor

But then you show this code

public DerivedClass(int i)
    : base(value)
{
    // Is it possible to set "value" here?
    // Logic
}

When that code block is entered you base class constructor has already run. You can however modify the value in an expression before passing it to the base constructor (with some obvious constraints). However, you will not have access to 'value' unless it is an input to the constructor.

Ed Swangren
See edit, I typed the comment on the wrong line.. Meant to type it below the base constructor call.
Ian P
OK, I see that others have suggested to you that you can modify the value before sending it to the base constructor.
Ed Swangren
+3  A: 

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;
    }
}
Don Kirkby
+1  A: 

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);
    }
}
Ricardo Lacerda Castelo Branco
+3  A: 

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
    }
}
GBegen
+1  A: 

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.

Pavel Minaev