5

This question already has an answer here:

I am aware that for the general case, the answer to "should I throw an exception from a property" is "generally don't, but in some special circumstances it is OK to do so". There is a Microsoft guideline which gives this general answer, and also a question on this site.

Now I am faced with a situation which I think may be one of those "special ones" where it is OK. My question: is this really one of those exceptional situations where throwing the exception is superior to the alternatives? Or is it better to use a getter/setter just like in the general case?

My application uses Linq2SQL, and there is the case where my object can be in invalid state because somebody or something wrote nonsense into the database. Consider this toy example:

[Table(Name="Rectangle")]
public class Rectangle {

[Column(Name="ID", IsPrimaryKey = true, IsDbGenerated = true)]
public int ID {get; set;} 

[Column(Name="firstSide")]
public double firstSide {get; set;} 

[Column(Name="secondSide")]
public double secondSide {get; set;} 

public double sideRatio 
{
    get
    {
            return firstSide/secondSide; 
    }
}
}

Here, I could write code which ensures that my application never writes a Rectangle with a zero-length side into the database. But no matter how bulletproof I make my own code, somebody could open the database with a different application and create an invalid Rectangle, especially one with a 0 for secondSide. (For this example, please forget that it is possible to design the database in a way such that writing a side length of zero into the rectangle table is impossible; my domain model is very complex and there are constraints on model state which cannot be expressed in a relational database).

So, the solution I am gravitating to is to change the getter to:

get 
{
     if(firstSide > 0 && secondSide > 0) return firstSide/secondSide; 
     else throw new System.InvalidOperationException("All rectangle sides should have a positive length"); 
}

The reasoning behind not throwing exceptions from properties is that programmers should be able to use them without having to make precautions about catching and handling them them. But in this case, I think that it is OK to continue to use this property without such precautions:

  • if the exception is thrown because my application wrote a non-zero rectangle side into the database, then this is a serious bug. It cannot and shouldn't be handled in the application, but there should be code which prevents it. It is good that the exception is visibly thrown, because that way the bug is caught.
  • if the exception is thrown because a different application changed the data in the database, then handling it is outside of the scope of my application. So I can't do anything about it if I catch it.

Is this a good enough reasoning to get over the "avoid" part of the guideline and throw the exception? Or should I turn it into a method after all? Note that in the real code, the properties which can have an invalid state feel less like the result of a calculation, so they are "natural" properties, not methods.

marked as duplicate by gnat, user40980, GlenH7, World Engineer Oct 23 '13 at 13:05

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    This is one of those cases that sounds good in theory "Never allow an object to be created that is invalid", but often fails when used in the real world. The reality is that many libraries that you are likely to use may not work and/or could become corrupted themselves if you throw an exception in situations that aren't expected. It wouldn't surprise me that a number of Microsoft Libraries fall into that category which is the reason for the recommendation. – Dunk Oct 15 '13 at 15:05
  • 1
    To those who think that this is a duplicate: Maybe I wasn't able to express my intention clearly enough. The other question asks, is it generally bad to throw the exception. The answer is: generally yes, but in special circumstances, it is allowed. The current question is: Is the situation I describe one of those special situations? As such, it complements the other question, and does not duplicate it. I would be glad for suggestions how to edit the question to make it more clear. – Rumi P. Oct 23 '13 at 15:20
  • Well, hang on, let's say you don't throw an exception. What are you going to return? How can your application reliably continue if you know full well your data is junk? Ideally in cases like this you should fail as early as you can, and if you can't fail at instantiation time then just fail as early as possible. You cannot continue from this scenario, your data is invalid! – Phoshi Oct 23 '13 at 15:30
2

From my point of view this is totally valid. Making sure that valid values are set is important, however if you are still unsure you maybe could move the logic to the constructor of the object (assuming that applies to your environment)

Also check this other post

Is throwing an exception from a property bad form?

1

You can choose to never let the application build an invalid instance of your object.

private double _firstSide;

[Column(Name="firstSide")]
public double FirstSide {
    get { return this._firstSide; }
    set 
    {
        if(value <= 0) throw new System.InvalidOperationException("All rectangle sides should have a positive length");
        this._firstSide = value;
    }
} 

private double _secondSide;

[Column(Name="secondSide")]
public double SecondSide
{
    get { return this._secondSide; }
    set 
    {
        if(value <= 0) throw new System.InvalidOperationException("All rectangle sides should have a positive length");
        this._secondSide = value;
    }
}

public double SideRatio 
{
    get
    {
        return this.FirstSide / this.SecondSide; // safe
    }
}

Handle the errors when you are building your instance / setting your properties. When it's time to do some algorithms, you can safely access SideRatio without the overhead to handle weird objects.

This way, you have a clear distinction between data access layer which will validate objects, and the use of this objects, which are guaranteed to be safe.

  • I'll count this as a vote in the "it is OK to throw exception from a property in this case" camp, because this is what your solution suggests to do. Note that the solution as proposed does not solve my problem, it works only as long as my code is the only agent which writes to the database, which in real life is not the case. I could put the validation into the get parts, refusing to build an object from wrong data, but it has its own problems (I either have to allow for null in entity refs and entity sets, which makes my objects unsafe again, or mock the whole object graph for tests). – Rumi P. Oct 22 '13 at 15:22
  • +1: it is much easier to understand exceptions when they are thrown as early as possible – kevin cline Oct 22 '13 at 15:22
  • Exceptions must not be thrown from a getter, but can be thrown from a setter, when the value is invalid, which is the case. msdn.microsoft.com/en-us/library/ms229006.aspx – Cyril Gandon Oct 22 '13 at 15:26
0

I think what you have in this example is a method not a property. When you code it as a method, you could define a range of valid return values (as the case in many .NET methods such as finding string within another, you get -1 if not found), this way the invoking code could determine the result of the operation rather easily.

If your presented example is just for simplification, then the general case would be to validate data before you create the object - That is partially what constructors are for: Where to put validation in domain models.

Anyway, I guess you can't make your object so gentle in such a way that the caller can use them quite safely without anticipating the possibility of an error. Your doco should advice the user that certain objects are to be created with care.

  • Yes, this was presented as a simplification, the actual code is usually a "real" property. And I cannot validate the data before I create it, it is Linq that creates the object automatically for me, using whatever data is present in the database. This is the whole point of the question - there are cases where I cannot validate first. – Rumi P. Oct 22 '13 at 7:33
  • Thanks for your clarification, in that case, I guess you have no choice! – NoChance Oct 22 '13 at 21:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.