Jasmine
Jasmine

Reputation: 5326

What happens if an exception occurs in Catch block in C#. Also what would be the caller result in that case

It was an interview question, quite simple, but I am not confident about the answer.

What happens if an exception occurs in catch block ?

I am trying to give an example small prog of what the interviewer was trying to ask me, please correct my program if it is not compiling, I am really new to this. Bottom line is what happens if an exception occurs in Catch and what will be the value of caller int hat case.

For instance, I have the following:

double Calculate(int x)
{
    try
    {
        x = x/2;
    }
    catch(Exception ex)
    {
        Console.Writeline("Message: "+ ex.Message);
    }
    finally
    {
      x = 10;
    }
    return x;
}

double myResult = Calculate(x); //x can be any number or 0 for example

Now there are two questions:

  1. What happens if an exception happens in catch block ? Also, how to resolve it ? (This is simple example of what the interviewer was asking a similar question).

  2. What will happen to myResult if an exception happens in Calculate(x) method ?What will be its value in all cases ? (Please explain every case with an example)

I would like to understand this with a detailed explanation too.

Thank you so much.

Upvotes: 32

Views: 49982

Answers (7)

dead_webdev
dead_webdev

Reputation: 256

To Explain it code wise . Here is the sample code using System;

public class Program
{
    public static double Calculate(int x)
    {
        try
        {
            x = 2 / x;
        }
        catch (ArithmeticException ae)
        {
            x = 2 / x;  // This will throw the error and programs terminates without returning any value.
            Console.WriteLine("Message: " + ae.Message);
        }
        catch (Exception ex)
        {                
            Console.WriteLine("Message: " + ex.Message);
        }

        finally
        {
            x = 10;
        }
        return x;
    }
    static void Main(string[] args)
    {
        double myResult = Program.Calculate(0);
        Console.WriteLine(myResult);
    }
}
}

The code behaves the same even if it is in catch block , unless there is try catch inside a catch block like this

public class Program
{
    public static double Calculate(int x)
    {
        try
        {
            x = 2 / x;
        }
        catch (ArithmeticException ae)
        {
            try
            {
                x = 2 / x;
            }
            catch(Exception ex1)
            {
                Console.WriteLine("Message: " + ex1.Message);
            }
            Console.WriteLine("Message: " + ae.Message);
        }
        catch (Exception ex)
        {                
            Console.WriteLine("Message: " + ex.Message);
        }

        finally
        {
            x = 10;
        }
        return x;
    }
    static void Main(string[] args)
    {
        double myResult = Program.Calculate(0);
        Console.WriteLine(myResult);
    }
}
}

Upvotes: 0

Justin W
Justin W

Reputation: 52

I agree with TheEvilPenguin. Just put a try/catch one more time in the catch portion. I didn't run the code, but the finally portion will always run regardless if there is an exception or not, therefore x is equal to 10.

Here is the crazy code I wrote today. As you can see, I put a try/catch in the catch portion of the code:

                     if (days >= 180 || inStock == false)
                    {

                        if (mainGetSet.OrderID != MainGetSet.EMAILCANCELO)
                        {
                            if (debugging == true)
                            {
                                MessageBox.Show("Here is where support will get an email instead of it being canceled. Order ID: " + mainGetSet.OrderID);
                            }
                            string subject = "Please check order " + mainGetSet.OrderID + " to ascertain if possible cancel action is needed.";
                            string body = "Dear Support \r\n \r\nPlease check order " + mainGetSet.OrderID + " to confirm if a possible cancel action is needed " +
                            "and please process manually. Here is the SKU " + childGetSet.Sku + ". Thank you. " +
                            " \r\n \r\n Kind Regards, \r\n IT Department";
                            sendEmail.SendEmailToSupport(subject, body);

                            // Database call to the cancel order DB
                            CanceledDB.AddJSONInfo(childGetSet);

                            //readyResponse = CancelKiboOrder.MakeOrderCanceled(token, mainGetSet.OrderID);
                        }
                        MainGetSet.EMAILCANCELO = mainGetSet.OrderID;

                    }
                    else
                    {
                        if (debugging == true)
                        {
                            MessageBox.Show("Here is where support will get an email about the backorder date. Order ID: " + mainGetSet.OrderID);
                        }
                        //DateTime backorder180 = new DateTime().AddDays(days);
                        //string backOrder = backorder180.ToString("yyyy-MM-dd'T'HH:mm:ss");
                        string backOrder = DateTime.UtcNow.AddDays(days).ToString("s") + "Z";

                        string ItemsQty = string.Empty;

                        for (int iq = 0; iq < jsonGetSet.OrderItemID.Count; iq++)
                        {
                            //ItemsQty += "{  \r\n        \"autoAssign\":false,\r\n        \"locationID\":169309,\r\n        \"shipmentStatus\":\"READY\",\r\n        \"itemAssign\":[  \r\n           {  \r\n              \"orderItemID\":" + jsonGetSet.OrderItemID[iq] + ",\r\n              \"quantity\":" + jsonGetSet.Quantity[iq] + "\r\n           }\r\n        ]\r\n     }\r\n";
                            ItemsQty += "    {\r\n         \"shipmentStatus\":\"BACKORDER\",\r\n         \"backOrderReleaseDate\":\"" + backOrder + "\",\r\n         \"itemAssign\":[\r\n            {\r\n               \"orderItemID\":" + jsonGetSet.OrderItemID[iq] + ",\r\n               \"quantity\":" + jsonGetSet.Quantity[iq] + "\r\n            }\r\n         ]\r\n      }\r\n ";
                            if (jsonGetSet.OrderItemID.Count > 0 && iq < jsonGetSet.OrderItemID.Count - 1)
                            {
                                ItemsQty += ",";
                            }
                        }
                        if (debugging == true)
                        {
                            MessageBox.Show(ItemsQty);
                        }

                        string subject = "Please check backorder number " + mainGetSet.OrderID + " to ascertain  the reason.";
                        string body = "Dear Support \r\n \r\nPlease check backorder number " + mainGetSet.OrderID + " to confirm  the backorder. " +
                            "Here is the SKU " + childGetSet.Sku + "."+
                            " \r\n \r\n Kind Regards, \r\n IT Department";
                        sendEmail.SendEmailToSupport(subject, body);

                        readyResponse = Backorder.MakeOrderBackorder(token, mainGetSet.OrderID, ItemsQty);
                    }

                    if (debugging == true)
                    {
                        DebugOutput(readyResponse, textBox);
                    }

                    var parsedReady = new JObject();
                    try
                    {



                        parsedReady = JObject.Parse(readyResponse);


                    }
                    catch (Exception JEx)
                    {
                        if (debugging == true)
                        {
                            MessageBox.Show("The program threw an Exception: " + JEx);
                        }
                        else
                        { 
                            string messageSubject = "There was a problem with the JSON for the BackOrder in KIBO.";
                            string messageBody = "There was a problem with the JSON for the BackOrder in KIBO. Error: " +
                                "\r\n \r\n \r\n Here is the JSON returned: " + parsedReady;
                            string kiboSendEmail = string.Empty;

                            kiboSendEmail = sendEmail.SendEmailCS(messageSubject, messageBody, JEx);

                            if (mainGetSet.OrderID != MainGetSet.EMAILCANCELO)
                            {
                                if (debugging == true)
                                {
                                    MessageBox.Show("Here is where support will get an email instead of it being canceled. Order ID: " + mainGetSet.OrderID);
                                }
                                string subject = "Please check order " + mainGetSet.OrderID + " to ascertain if possible cancel action is needed.";
                                string body = "Dear Support \r\n \r\nPlease check order " + mainGetSet.OrderID + " to confirm if a possible cancel action is needed " +
                                "and please process manually. Here is the SKU " + childGetSet.Sku + ". Thank you. " +
                                " \r\n \r\n Kind Regards, \r\n IT Department";
                                sendEmail.SendEmailToSupport(subject, body);

                                // Database call to the cancel order DB
                                CanceledDB.AddJSONInfo(childGetSet);

                                //readyResponse = CancelKiboOrder.MakeOrderCanceled(token, mainGetSet.OrderID);
                            }
                            MainGetSet.EMAILCANCELO = mainGetSet.OrderID;


                            {
                            if (debugging == true)
                            {
                                MessageBox.Show("Here is where support will get an email about the backorder date. Order ID: " + mainGetSet.OrderID);
                            }
                            //DateTime backorder180 = new DateTime().AddDays(days);
                            //string backOrder = backorder180.ToString("yyyy-MM-dd'T'HH:mm:ss");
                            string backOrder = DateTime.UtcNow.AddDays(days).ToString("s") + "Z";

                            string ItemsQty = string.Empty;

                            for (int iq = 0; iq < jsonGetSet.OrderItemID.Count; iq++)
                            {
                                //ItemsQty += "{  \r\n        \"autoAssign\":false,\r\n        \"locationID\":169309,\r\n        \"shipmentStatus\":\"READY\",\r\n        \"itemAssign\":[  \r\n           {  \r\n              \"orderItemID\":" + jsonGetSet.OrderItemID[iq] + ",\r\n              \"quantity\":" + jsonGetSet.Quantity[iq] + "\r\n           }\r\n        ]\r\n     }\r\n";
                                ItemsQty += "    {\r\n         \"shipmentStatus\":\"BACKORDER\",\r\n         \"backOrderReleaseDate\":\"" + backOrder + "\",\r\n         \"itemAssign\":[\r\n            {\r\n               \"orderItemID\":" + jsonGetSet.OrderItemID[iq] + ",\r\n               \"quantity\":" + jsonGetSet.Quantity[iq] + "\r\n            }\r\n         ]\r\n      }\r\n ";
                                if (jsonGetSet.OrderItemID.Count > 0 && iq < jsonGetSet.OrderItemID.Count - 1)
                                {
                                    ItemsQty += ",";
                                }
                            }
                            if (debugging == true)
                            {
                                MessageBox.Show(ItemsQty);
                            }

                            string subject = "Please check backorder number " + mainGetSet.OrderID + " to ascertain  the reason.";
                            string body = "Dear Support \r\n \r\nPlease check backorder number " + mainGetSet.OrderID + " to confirm  the backorder. " +
                                "Here is the SKU " + childGetSet.Sku + "." +
                                " \r\n \r\n Kind Regards, \r\n IT Department";
                            sendEmail.SendEmailToSupport(subject, body);

                            readyResponse = Backorder.MakeOrderBackorder(token, mainGetSet.OrderID, ItemsQty);
                        }

                        if (debugging == true)
                        {
                            DebugOutput(readyResponse, textBox);
                        }

                        parsedReady = new JObject();
                        try
                        {



                            parsedReady = JObject.Parse(readyResponse);


                        }
                        catch (Exception Jx)
                        {
                            if (debugging == true)
                            {
                                MessageBox.Show("The program threw an Exception: " + Jx);
                            }
                            else
                            {
                                messageSubject = "There was a problem with the JSON for the BackOrder in KIBO.";
                                messageBody = "There was a problem with the JSON for the BackOrder in KIBO. Error: " +
                                    "\r\n \r\n \r\n Here is the JSON returned: " + parsedReady;
                                kiboSendEmail = string.Empty;

                                kiboSendEmail = sendEmail.SendEmailCS(messageSubject, messageBody, JEx);






                            }

                        }

Upvotes: 0

In case if its a child function the exception will be sent to the catch block of calling function

In case if its a main function the exception would be thrown and either handled by a calling method or unhanded

Secondly we don't write anything in catch blocks which can cause an exception.

They are usually used to throw or log exception.

Even if there is something you can use the Finally block so that any occupied resources can be relased.

A common usage of catch and finally together is to obtain and use resources in a try block, deal with exceptional circumstances in a catch block, and release the resources in the finally block.

MSDN DOCUMENTATION

Upvotes: 1

TheEvilPenguin
TheEvilPenguin

Reputation: 5682

An exception thrown in a catch block will behave the same as an exception thrown without it - it will go up the stack until it is caught in a higher level catch block, if one exists. Doing this is quite normal if you want to change or wrap the original exception; i.e.:

public void MyStartMethod
{
    try
    {
        //do something
        MyBadMethod();
    }
    catch(MySpecialException mse)
    {
        //this is the higher level catch block, specifically catching MySpecialException 
    }
}

public void MyBadMethod()
{
    try
    {
        //do something silly that causes an exception
    }
    catch (Exception e)
    {
        //do some logging

        throw new MySpecialException(e);
    }
}

public class MySpecialException : Exception 
{   
    public MySpecialException(Exception e) { ...etc... }
}

In your case, myResult will have whatever value it had before, if it's even still in scope.

Upvotes: 31

TGH
TGH

Reputation: 39268

An exception in the catch will basically behave as if there was no catch block there to begin with. You see this pattern in multilayered code where you rethrow exceptions. This is a slight variation on your example, but the result is very similar.

try
{}
catch
{
  throw;
}

In the case above and in your case the exception is considered unhandled since it's still propagating up the stack.

There will be no return value. The program simply fails if there is no other catch block to deal with it.

Upvotes: 4

JuStDaN
JuStDaN

Reputation: 449

The info below will help (from a previous answer of mine to a related question). If your catch block throws an exception and there are no other catch blocks to handle it besides the one that caused it, it will continue to get re thrown then 'Windows handles it'.

If a exception occurs the CLR traverses up the call stack looking for a matching catch expression. If the CLR doen't finds a matching one, or the Exception gets re thrown each time, the Exception bubbles out of the Main() method. In that case Windows handles the Exception.

Event Handling of Console Applications is the easiest to understand, because there is no special Handling by the CLR. The Exception is leaving the Applications Thread if not caught. The CLR opens a window asking for debug or exit the application. If the user chooses to debug, the debugger starts. If the user chooses to close, the Application exits and the Exception is serialized and written to the console.

Upvotes: 3

Micha
Micha

Reputation: 5163

There is no real return-value. The exception will "return".

This is acceptable Code for compiler:

public bool fooMethod()
{
  throw new NotImplementedException();
}

In your case myResult will not be changed.

Upvotes: 0

Related Questions