Continue program after exception is caught?

Viewed 93

i know this question has been asked similarly quite often, but I can't seeem to find an answer that I'm satisfied with. I want do learn this "right" from the start.

string [] list = {"foo", "bar", "foo"};
for(int i = 0; i<list.Length;i++)
{
    try
    {
        //begin sql transaction
        if(!list[i].Equals("foo"))
            throw new Exception("foo exception");
        else
        {
            //save stuff into DB
            Console.WriteLine(list[i]);
            //commit transaction here
        }
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.Message);
        //rollback transaction here
    }
    Console.WriteLine("Next record");
}

I've tested the code in the following fiddle https://dotnetfiddle.net/0nftFD and now my questions:

If i were to handle files in a for loop analog to the above example and if one of them had an IO exception for example, i would log it, email to admin, etc. and then continue with the next file.

As far as i can see it would work like this, would this be good/bad practise? I'd like to learn this properly right away :)

EDIT: Because i failed to mention this before, I would also get specific exceptions.

Ressources i failed to see before:

  1. similar question: https://forums.asp.net/t/1943641.aspx?How+do+I+continue+after+an+exception+is+caught+
  2. .net site: https://docs.microsoft.com/de-de/dotnet/csharp/programming-guide/exceptions/using-exceptions
2 Answers

Depending on the requirements you might be able to separate the data processing and error handling:

  • Iterate through the files
  • In case of exception capture into enough information into a List, Dictionary to be able process later
  • After looping through all the object loop through the errors

For example:

string[] list = {"foo", "bar", "foo"};
var errors = new Dictionary<string, ExceptionDispatchInfo>();
for(int i = 0; i < list.Length; i++)
{
    try
    {
        if(!list[i].Equals("foo"))
            throw new Exception("foo exception");
        else
            Console.WriteLine(list[i]);
    }
    catch(Exception ex)
    {
       var edi = ExceptionDispatchInfo.Capture(ex);
       errors.Add($"{list[i]}_{i}", edi);
    }
    Console.WriteLine("Next record");
}

foreach(var error in errors)
{
    //Process error and throw the original exception if needed
    //error.Value.Throw();
} 

Your example is how to handle it, though you may wish to catch only specific exceptions and not all. In some cases you may want to exit the processing due to speicific exceptions - for instance - if your database is not reachable then no need to keep going through all the files only to find it fails on each iteration.

In that example you could nest the loop in a try catch also such that it may catch exception types that are thrown which you specifically wish to be terminal to the loop processing. An example of it being nested is shown below.

try
{
    for(int i=0; i < 100; i++)
    {
        try
        {
            //do something
        }
        catch(IOException ex)
        {
        }
    }
}
catch(SecurityException sex)
{
}

Incidentally - you might also consider that you can batch the database (depending how many files you might be processing) and make your changes in one go. That's a performance trade-off you might wish to consider.

Related