Suppose I have a class like this
class A
{
private int _x; //must be between [-10 10]
private int _y; //must be between [10 20]
}
Using properties I have a couple of variants for the variables
public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
throw new Exception("Some error text");
_x = value;
}
}
or
public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
return;
_x = value;
}
}
(same for _y).
In first case I’m not sure I want to use exceptions (they are slow and have other known problems). In second I’m paying for not using them with the ambiguity of values (in some different way for _x and _y).
Obviously I can use in my situation (if dealing with a list of objects) smth like that
public bool IsValid = true;
//...
public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
{
IsValid = false;
return;
}
_x = value;
}
}
class AWrapper
{
public List<A> AList {get; set;}
public AWrapper(List<A> list)
{
AList = list.Where(x => x.IsValid == true).ToList();
}
}
or some validator class or… I guess some other things. So I just want to form the criteria for myself – which technique is better and when…
Lets get something straight to start with; Exceptions may be "slow", but thats exactly why you only use them in exceptional circumstances.
In your case, if a number falling outside a given range is Exceptional (ie, should never happen) then you're fine to throw an exception. If, however, this is something like user-input then the user filling in a value outside of an acceptable range is definately not exceptional! In this case what you want is validation that the value entered is within an acceptable range.
Another point on this solution:
set
{
if (!(value >= -10 && value <= 10))
return;
_x = value;
}
This, IMO, is just as bad (if not worse). The reason being that if I set X=10
, I expect that when I read X
it has the value I just set.
Common approach is to raise InvalidArgumentException in such case. If you do not want to deal with exceptions you can introduce custom flag IsValid
(as you already mentioned).
To persist a property range I would suggest introduce custom attribute for this purposes and mark properties by it like:
public bool IsValid { }
[ValueRange(Max = 10, Min = 5)]
public int X
{
set
{
this.ValidateValueRange(this.X, value);
}
}
private bool ValidateValueRange(...)
{
// 1. Get property value (see link below regarding retrieving a property)
// 2. Get ValueRange attribute values
// 3. Update this.IsValid
// 4. Return ...
}
And then implement single method to check whether passed in value
is in range.
Useful links:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With