0

Let's suppose, that we have the following class:

class C
{
    private readonly DataType data;
    private readonly AdditionalType additional;

    C(DataType newData)
    {
        data = newData;
        // LONG code evaluating additional
    }

    C(OtherType newData)
    {
        // eval data from newData
        // the same LONG code evaluating additional
    }
}

Both data and additional remain unchanged through the whole life of C. However, there is a code smell: the section evaluating additional is doubled in both constructors. The natural choice is then to extract it to another method:

class C
{
    private readonly DataType data;
    private readonly AdditionalType additional;

    private void EvalAdditional()
    {
        // LONG code evaluating additional
    }

    C(DataType newData)
    {
        data = newData;
        EvalAdditional();
    }

    C(OtherType newData)
    {
        // eval data from newData
        EvalAdditional();
    }
}

But then additional no longer can be readonly (beacuse it is not initialized in ctor).

How to solve this problem in an elegant way?

Spook
  • 25,318
  • 18
  • 90
  • 167
  • 1
    Does the evaluation of `additional` depend on the constructor arguments? If not you can just move the evaluation to another private constructor and call that from your public constructors. – Lee Jun 22 '13 at 12:33
  • 1
    *...// LONG code...* evaluating anything in a constructor is a code smell in itself. From MSDN: Constructors should not do much work other than capture the constructor parameters. The cost of any other processing should be delayed until required. – inquisitive Jun 22 '13 at 12:43

3 Answers3

4

Just let the method EvalAdditional return the additional object (instead of void).

readonly DataType data;
readonly AdditionalType additional;

AdditionalType EvalAdditional()
{
    // LONG code evaluating additional
    return additional;
}

C(DataType newData)
{
    data = newData;
    additional = EvalAdditional();
}

C(OtherType newData)
{
    // eval data from newData
    additional = EvalAdditional();
}
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
2

If the evaluation of additional does not depend on the arguments given to the other constructors, you can just move it to a private constructor and call that from your public constructors:

private C()
{
    //long code evaluating additional
}

C(DataType newData)
    : this()
{
    data = newData;
}
Lee
  • 142,018
  • 20
  • 234
  • 287
0

You could do something like this:

C(DataType newData)
    :this ()
{
    data = newData;
}

C(OtherType newData)
    :this ()
{
    // eval data from newData
}

private C()
{
    EvalAdditional();
}

Although that depends heavily on what EvalAdditional is doing, you could pass parameters if required.

Chris
  • 8,268
  • 3
  • 33
  • 46