【问题标题】:C# exceptions and code breakingC# 异常和代码破坏
【发布时间】:2013-05-14 07:02:25
【问题描述】:

我有一个名为 TryMe 的方法,它有 try catch 块并捕获他的异常。
我从另一个班级给他打电话,但是当发生异常时,它不会停止代码执行。
示例:

public void TryMe()
{
    try
    {
        SomeMethod();
    }
    catch(Exception exception){
        MessageBox.Show(exception.Message);
    }
}


     //Method calling
     Actions CAactions = new Actions();
     CActions.TryMe();
     ///////////////////////////////////
     //If exception is handled it should stop to here.

     this.Hide();
     FormActions FormActions = new FormActions();

方法定义在类文件中。方法调用为windows形式。
问题是它只显示消息框并且代码继续执行。
我想在异常捕获后停止代码而不是隐藏表单。如果一切正常,它应该隐藏它。
可能是我的观念错了?

【问题讨论】:

    标签: c# windows winforms exception exception-handling


    【解决方案1】:

    最简单的解决方法是将您的函数更改为返回真/假,具体取决于它是否成功(即仅在 TryMe 方法未出错时隐藏表单):

     public bool TryMe()
     {
      try
       {
        SomeMethod();
        return true;
       }
       catch (Exception exception)
       {
        // log exception 
        return false;
       }
      }
    

    然后这样称呼它:

     if (CActions.TryMe())
     {
       this.Hide();
     }
    

    另一种选择是在显示消息后重新抛出异常,并让调用代码在 try catch 中处理它:

    public void TryMe()
    {
     try
     {
       SomeMethod();
      }
       catch (Exception exception)
      {
       // log exception? 
       throw;
      }
      }
    

    调用代码:

       try 
       {
         CActions.TryMe();
         this.Hide();
       }
       catch (Exception ex)
       {
          // error handling
        }
    

    【讨论】:

    • 谢谢!这是一个好的编码习惯吗?我是 C# 的新手,如果我的整个错误处理模型的想法是错误的,那么现在是改变它的最佳时机。 :)
    • 有很多选项 - 您可以从 TryMe 重新抛出错误(通过将 Throw() 放在 catch 块中)并让调用代码也处理错误
    • 当然,这是一个选项。但是哪一个是最好的?我的意思是准确的工作、干净和可读的代码之间的平衡?
    • 我认为它归结为如果异常是预期的并且你知道你的方法可以处理它,然后沿着 bool 路线走 - 如果异常只是这样 - 一个异常 - 然后是调用代码应该有 try/catch
    【解决方案2】:

    您应避免在任何地方调用 MessageBox.Show(),但应在应用程序的 UI 端(例如您的表单)。这被认为是一种不好的做法。所以我会修改 NDJ 的答案:

    public bool TryMe()
    {
       try
       {
           SomeMethod();
           return true;
       }
       catch (Exception exception)
       {
           //insert some logging here, if YOU need the callstack of your exception
           return false;
       }
    }
    
    if (CActions.TryMe())
    {
        this.Hide();
    }
    else
    {
        MessageBox.Show(...); //insert some meaningful message, useful to END-USER here, not some "Null refrence exception!!11" message, which no one but you will understand
    }
    

    【讨论】:

      【解决方案3】:

      另一个选择是将控制流委托给调用者,所以:

      public void TryMe()
      {
          try
          {
              SomeMethod();
          }
          catch(Exception exception){
             throw;
          }
      }
      

      并像使用它一样

       Actions CAactions = new Actions();
       try {
          CActions.TryMe();
          //continue, all ok.
       }
       catch(Excepiton ex) {
            //hide a form, exception happens inside a method
       }
      

      【讨论】:

      • 谢谢!但我想知道在表单类中有一个 try-catch 是否是一个好习惯?
      • @PaulReed:当然,这是做到这一点的方法之一。表单类是你的调用者,所以它知道如果某个调用失败或成功会发生什么。
      • throw exception; 将覆盖原始异常的调用堆栈。是有意的吗?通常最好只使用throw;
      【解决方案4】:

      正如您的代码所述,Exception 被捕获,它的Message 属性传递给MessageBox。这意味着,您的代码绝不会被中断或Exception 有机会冒泡。

      附带说明:在类 try/catch(或任何其他方法)中显示 MessageBox 被认为是一种不好的做法。这样做的原因很明显:它使您的类依赖于在图形应用程序环境中使用,这违背了类的可重用性。最好将Exception 传播到任何类型的应用程序都可以处理的方法返回类型,例如包含Message 和/或InnerException 文本的字符串。

      然后你可以做例如

      string methodResult = myObject.MyMethod();
      if(String.IsNullOrEmpty(myMethodResult)) //... everything worked out ok
      ...
      else //well then at least you have an error message to work with
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多