Throwing an exception is costly. The reasons are numerous, but its mostly due to the need to build the stack trace and cleanly exit the nested scope(s) until you find the appropriate catch
statement.
Actual performance will depend on the characteristics of your app. Take the following two blocks of code:
A:
if (foo.CanFizz)
foo.Fizz();
B:
try { foo.Fizz(); }
catch (NotFizzableException) { /* etc. */ }
Conventional wisdom would say that the first is faster, but if you expect foo.CanFizz
to be true most of the time, then the second may actually perform better. The cost of checking the guard condition every time may be higher than the cost of catching the exception in the unusual case that the guard condition is false.
Of course, premature optimization is the root of all evil. Don't even bother to think about this until you know that this is a performance bottleneck.