28

这是一个面试问题,很简单,但我对答案没有信心。

如果 catch 块中发生异常会发生什么?

我试图举一个面试官试图问我的小程序的例子,如果我的程序没有编译,请更正我的程序,我对此真的很陌生。底线是如果 Catch 中发生异常会发生什么,以及调用者 int hat case 的值是什么。

例如,我有以下内容:

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

现在有两个问题:

  1. 如果 catch 块中发生异常会发生什么?还有,怎么解决?(这是面试官提出类似问题的简单示例)。

  2. 如果Calculate(x) 方法中发生异常,myResult 会发生什么?在所有情况下它的值是多少?(请举例说明每一个案例)

我也想通过详细的解释来理解这一点。

太感谢了。

4

7 回答 7

29

catch块中抛出的异常与没有它时抛出的异常行为相同——它将向上堆栈,直到它被更高级别的 catch 块捕获(如果存在)。如果要更改或包装原始异常,这样做是很正常的;IE:

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... }
}

就您而言myResult,如果它仍在范围内,它将具有以前的任何价值。

于 2013-10-10T05:07:30.000 回答
3

下面的信息将有所帮助(从我以前的回答到相关问题)。如果您的 catch 块抛出异常,并且除了导致它的那个之外没有其他 catch 块来处理它,它将继续被重新抛出,然后“Windows 处理它”。

如果发生异常,CLR 会向上遍历调用堆栈以寻找匹配的 catch 表达式。如果 CLR 没有找到匹配的,或者每次都重新抛出异常,则异常会从 Main() 方法中冒出。在这种情况下,Windows 会处理异常。

控制台应用程序的事件处理是最容易理解的,因为 CLR 没有特殊处理。如果没有被捕获,异常将离开应用程序线程。CLR 打开一个窗口,要求调试或退出应用程序。如果用户选择调试,调试器就会启动。如果用户选择关闭,则应用程序退出并且异常被序列化并写入控制台。

于 2013-10-10T05:18:12.863 回答
3

catch 中的异常基本上表现得好像一开始就没有 catch 块。您可以在重新引发异常的多层代码中看到这种模式。这与您的示例略有不同,但结果非常相似。

try
{}
catch
{
  throw;
}

在上述情况和您的情况下,异常被认为是未处理的,因为它仍在向上传播堆栈。

不会有返回值。如果没有其他 catch 块来处理它,程序就会失败。

于 2013-10-10T05:19:08.823 回答
1

如果它是一个子函数,异常将被发送到调用函数的 catch 块

如果它是主要功能,则会抛出异常并由调用方法处理或无人处理

其次,我们不会在catch块中写入任何可能导致异常的内容。

它们通常用于抛出或记录异常。

即使有什么你可以使用该Finally块,以便可以释放任何占用的资源。

catch 和 finally 一起的常见用法是在 try 块中获取和使用资源,在 catch 块中处理异常情况,并在 finally 块中释放资源。

MSDN 文档

于 2013-10-10T05:04:40.860 回答
0

没有真正的返回值。异常将“返回”。

这是编译器可接受的代码:

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

在你的情况下myResult不会改变。

于 2013-10-10T05:08:25.087 回答
0

解释它的代码明智。这是使用 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);
    }
}
}

即使在 catch 块中,代码的行为也是相同的,除非在这样的 catch 块中存在 try catch

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);
    }
}
}
于 2020-01-27T17:22:02.813 回答
0

我同意 TheEvilPenguin 的观点。只需在 catch 部分再放一次 try/catch 即可。我没有运行代码,但不管是否有异常,finally 部分都会一直运行,因此 x 等于 10。

这是我今天写的疯狂代码。如您所见,我在代码的 catch 部分放置了一个 try/catch:

                     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);






                            }

                        }
于 2018-09-25T18:48:18.730 回答