8

Good morning! I'm writing a class for drawing histograms and, for user's convenience, I've decided to add a few convenience constructors.

However, as soon as I recently switched to .NET code contracts from DevLabs, I want to make full use of preconditions for protection against my own (or someone's) stupidity.

    public HistoGrapher(IList<string> points, IList<T> values)
        : this(points.Select((point, pointIndex) => new KeyValuePair<string, T>(point, values[pointIndex])))
    {
        Contract.Requires<ArgumentNullException>(points != null, "points");
        Contract.Requires<ArgumentNullException>(values != null, "values");
        Contract.Requires<ArgumentException>(points.Count == values.Count, "The lengths of the lists should be equal.");
    }

    public HistoGrapher(IEnumerable<KeyValuePair<string, T>> pointValuePairs)
    {
        // useful code goes here
    }

There is a thing that confuses me. I don't want the first constructor to ever call the second one if the contract is broken; however, it is supposed that a call to this(...) will be performed before executing the body of the first constructor.

Will this code work as I want? I haven't tried yet. And if not, is there a capability of solving such an issue?

Christopher Bottoms
  • 11,218
  • 8
  • 50
  • 99
wh1t3cat1k
  • 3,146
  • 6
  • 32
  • 38

1 Answers1

5

And if not, is there a capability of solving such an issue?

Since the constructor body is only executed after calling the other constructor I don't think your current approach can work. I would recommend factoring out the common code into a separate method i.e. Init() that you can then call from both constructors, that would keep your code DRY and solve your problem:

public class HistoGrapher
{

    public HistoGrapher(IList<string> points, IList<T> values)
    {
        Contract.Requires<ArgumentNullException>(points != null, "points");
        Contract.Requires<ArgumentNullException>(values != null, "values");
        Contract.Requires<ArgumentException>(points.Count == values.Count, "The lengths of the lists should be equal.");

        var pointValuePairs = points.Select((point, pointIndex) => new KeyValuePair<string, T>(point, values[pointIndex]))
        Init(pointValuePairs);
    }

    public HistoGrapher(IEnumerable<KeyValuePair<string, T>> pointValuePairs)
    {
        Init(pointValuePairs);
    }

    private void Init(IEnumerable<KeyValuePair<string, T>> pointValuePairs)
    {
         // useful code goes here
    }
}
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335