Reputation: 28152
I have a Prize object that has a constructor with a single int parameter pence. I don't want ot allow negative values to be passed in. What is the best way to enforce this restriction? Shall I throw an exception from constructor? Or write a factory method?
EDIT: The Prize object was used as an example of a general role. Using uint is a good answer in this specific example not as a general role. I use 3.5 without additional code contracts libraries.
Upvotes: 0
Views: 330
Reputation: 1490
The design choice of how you construct an instance (ctor or factory) is independent of argument validation. Usually you should favor constructors (for example, see this answer for a relevant excerpt from Framework Design Guidelines):
When to use Factory method pattern?
The simple way to validate arguments are, of course, guard clauses that throw the appropriate exception:
public Prize(int pence)
{
if (pence < 0)
{
throw new ArgumentException(...);
}
/* Do stuff */
}
Then there's also Code Contracts that you may want to look into. I think those allow you to annotate your requirements, but I haven't had the opportunity to try them yet.
Upvotes: 1
Reputation: 20357
I agree with BrokenGlass 100%.
One 'trick' that you can use to have an int property on the prize object only allow positive integers without changing the data type to uint is:
public class Prize
{
private int _pence = 0;
public int Pence
{
get { return _pence; }
set { _pence = Math.Max(value, 0); }
}
public Price(int pence)
{
Pence = pence;
}
}
This doesn't prevent one from using reflection to set a negative number when using your class, but it does prevent negatives from being entered normally.
If you don't want to silently ignore negative values, you could throw an exception or even call Math.Abs
.
Upvotes: 0
Reputation: 36896
Just as you would use an int
instead of a string
to enforce passing in a valid integer, if you want only non-negative integers, how about using the appropriate type: uint
.
Upvotes: 0
Reputation: 160862
I have a Prize object that has a constructor with a single int parameter pence. I don't want ot allow negative values to be passed in.
Why don't you use the uint
datatype for pence
instead? Then it's guaranteed already that it's a positive value and you don't have to enforce this constraint yourself.
In general for enforcing constraints the mantra is "fail as soon as possible" (also see fail fast) so you should either throw an exception in the constructor or enforce your constraints with a code contract. I don't really see how a factory method would help in this context.
Upvotes: 3