PDA

View Full Version : Exception Handling


maskedmelon
08-06-2018, 07:44 PM
Are C# try-catch blocks very expensive? Seems to me the only cost is really the code inside it, plus some constant for flagging it a "try." Doesn't seem much different than using conditional "if" statements except it is a bigger blanket and non-specific . I guess that is a pretty big difference depending on what you are doing ^^ anyhoo, just curious!

loramin
08-06-2018, 08:17 PM
Not a C person myself, but I thought try/catch statements were less performant than if/else statements, so I looked it up ...
https://stackoverflow.com/questions/8687113/if-condition-vs-exception-handler

From the second answer:
Exception handling is a heavy and expensive operation as far as performance is concerned. If you can avoid catching an exception by using proper if else that can increase application's performance

maskedmelon
08-07-2018, 09:38 AM
thanks lor! I've seen that claim and also that it doesn't matter and was wondering more about the complexity of a try-catch block so that I can weigh its cost against alternatives ^^ liek, in some situations, i may need to write more instructions to code around it. the specific situation that I was dealing with:


public static void Execute(string command)
{
UserCommand Commands = new UserCommand();

try
{
if (command.Contains(" "))
{
string filePath = command.Substring(command.IndexOf(" ") + 1);
command = command.Substring(0, command.IndexOf(" "));
int commandIndex = UserCommand.CommandList.IndexOf((from x in UserCommand.CommandList where x.Equals(command, StringComparison.OrdinalIgnoreCase) select x).First());
//if (UserCommand.CommandList.Any(x => x.Equals(command, StringComparison.OrdinalIgnoreCase)))
Commands.GetType().GetMethod(UserCommand.CommandLi st[commandIndex], new Type[] { typeof(string) }).Invoke(Commands, new object[] { filePath });
}
else
{
int commandIndex = UserCommand.CommandList.IndexOf((from x in UserCommand.CommandList where x.Equals(command, StringComparison.OrdinalIgnoreCase) select x).First());
Commands.GetType().GetMethod(UserCommand.CommandLi st[commandIndex], new Type[0]).Invoke(Commands, new object[0]);
}
}
catch
{
Console.WriteLine("Invalid input");
}
}


if I didn't utilize the try-catch block, then I'd have to include two copies of that "if" line that i have commented out in addition to their else clauses and possible more conditionals if i added parameters to the method.

The try-catch block at least appeared to me to run in constant time, but I wasn't sure if there was some other mystical voodo beneath the hood that increased the complexity of it.

maskedmelon
08-07-2018, 11:25 AM
forgot to mention, the constant time assumes there is no exception thrown. if there is an exception thrown then the cost would be linear time as a function of th number of instructions in the block, no? Basically if an exception is thrown near the end of a try catch block, then you wasted a bunch of time that could have been saved by one or more conditionals (unless it can't be results over that way). I'd think it'd be more common for an exception to be thrown at the beginning of a try block though since it isn't really used unless you expect a potential exception throw in the next line of code. And, if you expect exceptions later on, you'd have to introduce conditionals to resolve those if you didn't use a try-catch block, no?

loramin
08-07-2018, 11:25 AM
Well again, not a C guy, so I can't comment on the performance specifics of try/catch vs. if/else in C. I'm almost certain that there is some sort of cost to try/catch, but I'm also a very strong believer in one of Donald Knuth's famous quotes:

Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.

However, even if you forget about performance, what I can say is that in any language there is real value in "doing things the way everyone else does them", both because A) if everyone else does it that way, there's probably a good reason, and B) even if there isn't, code readability is critically important. In other words, if people are used to reading if/elses, then using try/catches (even if they are equal performance-wise) is a bad idea because it makes it harder for others to read and understand your code.

(As an aside, a very common misconception among programming learners is that your computer/compiler is the primary "reader" of your source code. This misconception isn't actually one at first, when you're just working on your own code and learning. However, in a professional environment your code gets read by one or more peer reviewers when you first check it in, then again by you or someone else in the future everytime a bug gets fixed or a new feature gets added that relates to that code. If you piss off the compiler with uncompilable code you can fix it in a few seconds, but if you piss off the humans with unreadable you can waste hours if not days of people's time.)

As for:

if I didn't utilize the try-catch block, then I'd have to include two copies of that "if" line that i have commented out in addition to their else clauses and possible more conditionals if i added parameters to the method.

On the face of it (and again, I'm not a C guy, but in most languages ...) that means you should refactor that logic out into a separate function. Then you can use as many if/else or try/catch blocks as you want and just call that function however many times you want, while still keeping your code DRY (ie. following the best practice of "Don't Repeat Yourself").

maskedmelon
08-07-2018, 11:53 AM
that makes sense ^^ I thought about refactoring that whole method because I'm sure there's got to be a more direct way to do what im doing there. I'd considered peeling the one repeated item into its own method, but left it since it was one line of code repeated once. Of course if I introduce additional parameters or dump the try-catch block, I think I will roll into all into its own method. Im gonna remember that acronym ^^ I liek it ^^

loramin
08-07-2018, 12:53 PM
YAGNI (you ain’t gunna need it)

Another acronym that's critically important to programming :D

maskedmelon
08-07-2018, 01:16 PM
Many software devs start by try catch blocking every line they write. Once you adhere to the principles of YAGNI (you ain’t gunna need it) you will find yourself writing more code that is better performance with less errors. Engineering is all about using the least amount of parts to achieve the maximum effect. Less dependencies means less chances at fault.

i can see that. i had considered doing the same thing ^^;, but noticed it conspicuously absent from virtually every code snippet in any question I looked up. it made me wonder what the real cost was, so i could weigh when to use it.