I always felt that expecting exceptions to be thrown on a regular basis and using them as flow logic was a bad thing. Exceptions feel like they should be, well, the "exception". If you're expecting and planning for an exception, that would seem to indicate that your code should be refactored, at least in .NET...
However. A recent scenario gave me pause. I posted this on msdn a while ago, but I'd like to generate more discussion about it and this is the perfect place!
So, say you've got a database table which has a foreign key for several other tables (in the case that originally prompted the debate, there were 4 foreign keys pointing to it). You want to allow the user to delete, but only if there are NO foreign key references; you DON'T want to cascade delete.
I normally just do a check to see if there are any references, and if there are, I inform the user instead of doing the delete. It's very easy and relaxing to write that in LINQ as related tables are members on the object, so Section.Projects and Section.Categories and et cetera is nice to type with intellisense and all...
But the fact is that LINQ then has to hit potentially all 4 tables to see if there are any result rows pointing to that record, and hitting the database is obviously always a relatively expensive operation.
The lead on this project asked me to change it to just catch a SqlException with a code of 547 (foreign key constraint) and deal with it that way.
I was...
resistant.
But in this case, it's probably a lot more efficient to swallow the exception-related overhead than to swallow the 4 table hits... Especially since we have to do the check in every case, but we're spared the exception in the case when there are no children...
Plus the database really should be the one responsible for handling referential integrity, that's its job and it does it well...
So they won and I changed it.