.NET 内部函数抛出异常时如何退出外部函数

.NET How to Exit from Outer Function when Inner Function Throws Exception

我在一段代码中无法正确控制流程。我有一个函数 GetVoucherNumberAndApplyToDatabase(),它调用一个单独的函数 doPatientEncounterCreate()。如果内部函数抛出异常,我希望外部函数停止它在那里所做的事情,因为它取决于返回的返回值。

为清楚起见,这里是代码:

    //outer function
    private int GetVoucherNumberAndApplyToDatabase(int Mode)
    {
        int ProviderID = 0;
        int PracticeMRNumber = 0;
        int VoucherNumber = 0;
        string EncounterD = DateTime.Now.ToString("MM\/dd\/yyyy");
        try
        {
            EncounterCreateResults = doPatientEncounterCreate(practiceID, PracticeMRNumber, ProviderID, ddlVisitType.SelectedValue, EncounterD);

            /*
            if (EncounterCreateResults.ErrorMessage.Length > 0)
            {
                throw Exception;
            }
            */

            ...

            //fails bc doPatientEncounterCreate threw exception
            ApplyVoucherNumberToBillingCharges(practiceID, ReasonCodeID);
        }
        catch (ReasonCodeException ex)
        {
            pnlError.Visible = true;
            lblErrorMessage.Text = ex.Message;
        }
        catch (Exception ex)
        {
            pnlError.Visible = true;
            lblErrorMessage.Text = "An error occurred attempting to call the API: " + ex.Message;  
        }

    }

    //inner function
    public static EncounterResults doPatientEncounterCreate(int PracticeID, int PatientID
                                                  , int ProviderID, string ReasonCodeID, string EncounterD)
    {
        try
        {
            DataTable ReasonCodeDT = getSingleReasonCode(PracticeID, ReasonCodeID);

            string strReasonCode = String.Empty;
            string strReasonDescription = String.Empty;
            string strDuration = String.Empty;
            string strActive = String.Empty;

            if (ReasonCodeDT.Rows.Count != 1)
            {
                string strPracticeID = PracticeID.ToString();
                string PracticeName = getSingleStringResultFromSQL("SELECT @result ...); 
                string RecordCount = ReasonCodeDT.Rows.Count.ToString();
                throw new ReasonCodeException("Database Returned " + RecordCount + " Records for ReasonCodeID " + ReasonCodeID + " for Practice " + PracticeName + " (" + strPracticeID + ")");
            }
            else
            {
                DataRow Row = ReasonCodeDT.Rows[0];
                strReasonCode = Row["ReasonCodeID"].ToString();
                strReasonDescription = Row["Description"].ToString();
                strDuration = Row["Duration"].ToString();
                strActive = Row["Active"].ToString().ToLower();
            }

            string strReasonID = @"""ReasonCode"": {""Code"": """ + strReasonCode + @""", ""Description"":""" + strReasonDescription + @"""" +
                                @", ""Duration"": " + strDuration + @", ""Active"": " + strActive + @"}, ";
        }
        /*
        catch (ReasonCodeException ex)
        {
            Results.ErrorMessage = ex.Message;
            return Results;
        }*/
        catch (Exception ex)
        {
            ErrorLog.LogError(ex, "doPatientEncounterCreate Failed.", Convert.ToInt32(au.UserID), "");
            Results.ErrorMessage = ex.ToString();
            return Results;
        }
    }

    //Custom Exception Class used in doPatientEncounterCreate
    class ReasonCodeException : Exception
    {
        public ReasonCodeException()
        {

        }

        public ReasonCodeException(string Message):
            base ()
        {
            ErrorLog.LogError(Message);
        }

    }

我采纳了这个问题的第二个答案的建议:Exit all functions from code in inner function

然而,即使我已将我的 ReasonCodeException catch 块移动到外部函数,当代码为 运行 时,内部函数 doPatientEncounterCreate() 中会抛出一个通用异常然后代码在 oter 函数中继续,直到抛出异常,因为它缺少从内部函数返回的值。

此外,我无法遵循上述问题的已接受答案的建议,因为内部函数不是 void 函数,我需要返回值。

非常感谢您提供的任何帮助。

对于您要实现的目标,您是否可以在 doPatientEncounterCreate 方法中完全不使用 try catch 块?

这将允许您的 GetVoucherNumberAndApplyToDatabase 方法中的 try catch 块捕获 doPatientEncounterCreate 中发生的任何异常。

如果您需要在内部方法中使用 try catch 块,那么正如评论中 binDebug 所建议的那样,在 catch 块中执行您需要的操作然后重新抛出您的外部方法对我来说很有意义方法捕获它。

为了阐明 "rethrow" 的意思,这里引用了 example。并且,这是一个简短的片段示例:

catch(Exception e)
{
    // do something
    throw;
}

现在,您已经注释掉了特定的异常捕获并且只处理了通用的异常捕获(它也捕获了特定的异常)。

现在您不会重新抛出异常,只会返回有效响应。

根据您的需要,您可以通过记录等方式将任何特定异常作为子异常中的适当逻辑链进行处理,然后重新抛出。 请注意,有 2 种重新抛出机制可用,"throw" 和 "throw ex"。在这里你需要做一个抛出,因为它会保留堆栈跟踪而不创建嵌套的内部异常。

另一种方法是不处理内部函数中的任何异常,而让更高级别的函数进行处理,通常是在管道级别。 理想情况下,所有已知的异常都应在发生时处理,而任何未知的异常都应在全局顶层进行一般处理