如果在 C# 中的 Catch 块中发生异常会发生什么。在这种情况下,调用者的结果是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19287426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:38:45  来源:igfitidea点击:

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

c#asp.net.netc#-4.0exception

提问by Learner

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

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

What happens if an exception occurs in catch block ?

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

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.

我正在尝试举例说明面试官试图问我的问题,如果我的程序没有编译,请更正我的程序,我对此很陌生。底线是如果在 Catch 中发生异常会发生什么,以及 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)

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

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

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

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

Thank you so much.

非常感谢。

采纳答案by TheEvilPenguin

An exception thrown in a catchblock 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.:

在一个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... }
}

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

在您的情况下,myResult如果它仍在范围内,它将具有它以前的任何价值。

回答by Vinay Pratap Singh

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

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

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 catchblocks which can cause an exception.

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

They are usually used to throw or log exception.

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

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

即使有什么东西你可以使用这个Finally块,这样任何被占用的资源都可以被释放。

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.

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

MSDN DOCUMENTATION

MSDN文档

回答by Micha

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 myResultwill not be changed.

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

回答by JuStDaN

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

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

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.

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

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

回答by TGH

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.

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

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.

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

回答by Justin W

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.

我同意 TheEvilPenguin。只需在 catch 部分再放一次 try/catch。我没有运行代码,但是无论是否有异常,finally 部分都会一直运行,因此 x 等于 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:

这是我今天写的疯狂代码。如您所见,我在代码的 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);






                            }

                        }

回答by dead_webdev

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

以代码方式解释它。这是使用 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

即使在 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);
    }
}
}