In our third attempt, then, we look at cases where it is the normal course of business to have non-int values (if. For example, if a collection of these values may contain multiple non-integer entries), so. This means an exception handler may be the wrong approach.
In that case, it looks a good case for a structure which passes the int, and the rationale. Again, this ratiojnalerationale can just be a const like the above, but instead of holding both in the same int, you store them as distinct parts of a structure. And when it'sInitially, we have the rule that if the rationale is set, the int will not be set. But we are no longer tied to this rule; we can provide rationales for valid numbers too, if needs be.
ButEither way, every time you call it, you still need boilerplate, to pull outtest the rationale, check that it hasn't been set to see if the int is valid, then pull out and use the int part if the rationale lets us.
This is where you need to investigate your rationale forreasoning behind "don't use null".
If thea caller is calling this method and ignoring the "rationale" part of the structure completely, expecting a number without any error handling, and it gets a zero, then it'll handle the zero as a number, and be wrong. If it gets a magic number, it'll treat that as a number, and be wrong. But if it gets a null, it'll fall over, as it damn well should do.
So every time you call this method you must put in checks for its return value, however you handle the invalid values, whether in-band or out of band, try/catch, checking the struct for a "rationale" component, checking the int for a magic number, or checking an int for a null...
The alternative, to handle multiplication of an output which might contain an invalid int and a rationale like "My dog ate this measurement", is to overload the multiplication operator for that structure. And
...And then overload every other operator in your application that might get applied to this data. And
...And then overload all methods that might take ints. And
...And all of those overloads will need to still contain checks for invalid ints, just so that you can treat the return type of this one method as if it were always a valid int at the point when you are calling it.
- YouIf you have invalid values, you can't avoid checking for those invalid values at any point in the code where you're handling invalidthe values.
- If you're returning anything other than an int, you're not returning an int, so you can't treat it like an int. Operator overloading lets you pretendpretend to, but that's just pretend.
- An int with magic numbers (including NULL, NAN, Inf...) is no longer really an int, it's a poor-man's struct.
- Avoiding nulls will not make code more robust, it will just hide the problems with ints, or move them into a complex exception-handling structure.