web-dev-qa-db-ja.com

C#のCatchブロックで例外が発生した場合はどうなりますか。その場合の呼び出し元の結果もどうなるでしょうか

面接の質問でしたが、とても簡単ですが、私は答えに自信がありません。

Catchブロックで例外が発生するとどうなりますか?

私はインタビュアーが私に尋ねようとしていたことの小さな例を挙げようとしています。コンパイルされていない場合はプログラムを修正してください。これは本当に初めてです。一番下の行は、Catchで例外が発生した場合に何が発生するか、およびケースの呼び出し側の値が何になるかです。

たとえば、私は次のとおりです。

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

ここで2つの質問があります。

  1. Catchブロックで例外が発生するとどうなりますか?また、それを解決する方法は? (これは、インタビュアーが同様の質問をしたことの簡単な例です)。

  2. Calculate(x)メソッドで例外が発生した場合、myResultはどうなりますか? (すべてのケースを例で説明してください)

これも詳しい説明で理解したいと思います。

どうもありがとうございます。

23
Learner

catchブロックでスローされた例外は、それなしでスローされた例外と同じように動作します。より高いレベルのcatchブロックが存在する場合は、それがキャッチされるまでスタックを上に向かっていきます。元の例外を変更またはラップしたい場合、これを行うのは非常に正常です。例:

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は、それがまだスコープ内にある場合でも、以前の値になります。

26
TheEvilPenguin

以下の情報が役立ちます(以前の私の回答から関連する質問まで)。 catchブロックが例外をスローし、それを引き起こしたもの以外にそれを処理する他のcatchブロックが存在しない場合は、再スローされ続け、「Windowsが処理する」。

例外が発生した場合、CLRは、一致するキャッチ式を探すために呼び出しスタックをたどります。 CLRが一致するものを見つけられない場合、または毎回例外がスローされる場合、例外はMain()メソッドからバブリングします。その場合、Windowsが例外を処理します。

CLRによる特別な処理はないため、コンソールアプリケーションのイベント処理が最も簡単に理解できます。キャッチされない場合、例外はアプリケーションスレッドを離れます。 CLRは、デバッグを要求するか、アプリケーションを終了するウィンドウを開きます。ユーザーがデバッグを選択すると、デバッガーが起動します。ユーザーが閉じることを選択すると、アプリケーションが終了し、例外がシリアル化されてコンソールに書き込まれます。

3
JuStDaN

キャッチの例外は、基本的に、そもそもキャッチブロックがないかのように動作します。このパターンは、例外を再スローする多層コードで見られます。これは例のわずかなバリエーションですが、結果は非常に似ています。

try
{}
catch
{
  throw;
}

上記の場合とあなたの場合、例外はまだスタックに伝播しているため、未処理と見なされます。

戻り値はありません。それを処理する他のcatchブロックがない場合、プログラムは単に失敗します。

2
TGH

その子関数の場合、例外は呼び出し側関数のcatchブロックに送信されます

そのメイン関数の場合、例外がスローされ、呼び出しメソッドによって処理されるか、またはハンドレスで処理されます

次に、例外を引き起こす可能性があるcatchブロックには何も記述しません。

これらは通常、例外をスローまたはログに記録するために使用されます。

何かがある場合でも、Finallyブロックを使用して、占有されているリソースを解放することができます。

Catchおよびfinallyの一般的な使用方法は、tryブロックでリソースを取得して使用し、catchブロックで例外的な状況に対処し、finallyブロックでリソースを解放することです。

MSDN文書

1

TheEvilPenguinに同意します。キャッチ部分にもう一度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);






                            }

                        }
0
Justin W

実際の戻り値はありません。例外は「戻ります」。

これはコンパイラにとって許容できるコードです:

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

あなたの場合myResultは変更されません。

0
Micha

それを説明するためにコードを賢く。 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ブロック内にtry catchがない限り、コードは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);
    }
}
}
0
dead_webdev