Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which technique is correct if not using exceptions?

Tags:

c#

.net

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…

like image 479
Alex Kovanev Avatar asked Dec 22 '22 07:12

Alex Kovanev


2 Answers

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.

like image 103
Jamiec Avatar answered Jan 10 '23 23:01

Jamiec


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:

  • Creating Custom Attributes (C# Programming Guide)
  • How To Get A Property Name Using Lambda Expression in C# 3.
like image 33
sll Avatar answered Jan 10 '23 21:01

sll