【问题标题】:a question about exception in c#关于c#异常的问题
【发布时间】:2011-05-07 08:26:51
【问题描述】:

下面是代码sn-p:

class xxx
{

  public xxx(){}

  try
  {
    throw new Exception(InvalidoperationException);
  }
  catch(Exception x)
  {
  }
  catch(InvalidoperationException x)
  {
  }
}

谁能告诉这里会引发哪个异常以及它背后的原因是什么。

【问题讨论】:

  • "下面是一个代码 sn-p" - 不是可以编译的。

标签: c# .net exception exception-handling invalidoperationexception


【解决方案1】:

哇,这里有很多问题。从哪里开始?

  1. 该代码无法编译。您定义的 try-catch 块在任何方法之外,这是不允许的。您需要将它移动到方法的内部

  2. 切勿抛出您打算稍后在该方法中捕获的方法。这通常称为对“流控制”使用异常,这是完全不鼓励的。这样做会带来性能成本,并且当您有代码抛出和捕获自己的异常时,监视使用调试器时抛出的异常也会变得非常混乱。如有必要,使用布尔变量(称为标志)进行流量控制。

  3. 始终首先捕获派生的异常类。这意味着您应该首先捕获InvalidOperationException尝试捕获Exception。您需要颠倒您拥有的代码中 catch 块的顺序。

  4. 您实际上应该永远抓住System.Exception。您应该捕获的唯一例外是那些您明确理解并能够处理的例外。当您拥有的唯一信息是引发了一般异常时,您几乎无法知道出了什么问题或如何处理它。

    按照同样的思路,您还应该从不从您自己的代码中抛出此异常。选择一个从System.Exception 基类继承的更具描述性的异常类,或者通过从该类继承来创建自己的异常类。


我看到其他答案正在向您展示您的代码应该是什么样子的示例代码,如果它被重写。我不会那样做,因为如果我重写你的代码是正确的,我会得到这个:

class Xxx
{
    public Xxx()
    {

    }
}

不是特别有用。

【讨论】:

  • 性能成本(不使用调试器时)通常被夸大了;但是,我同意这仍然不是一个好主意。我不同意“永远抓不到System.Exception;例如,“记录并重新抛出”,或者其他一些并非不合理的情况。
  • @Marc:记录未处理的异常几乎总是比捕获和重新抛出更好的方法。对于 WinForms,AppDomain.UnhandledException 是一个很好的起点。我也不太喜欢笼统的陈述,但几乎在每种情况下,我都看到代码捕获System.Exception,这是错误的。除了顶级异常处理程序之外,您当然不应该在任何地方捕获System.Exception。这不是上面代码演示的内容。
  • 如果你点击UnhandledException,你的应用就完蛋了;并且有许多例外不会遇到这种情况 - 当然,它们非常严重无论如何,因此可能无法通过任何途径捕获。
【解决方案2】:

如果代码是这样的

 class xxx
    {

      public xxx(){

      try
      {
        throw new Exception(InvalidoperationException);
      }

      catch(InvalidoperationException x)
      {
      }

catch(异常 x) { } } }

它应该编译并引发您的异常并捕获。否则你的代码将根本无法编译。

【讨论】:

  • 这是什么逻辑?它永远不会编译。
  • 是的,它不会编译,因为“异常”类应该在任何其他类的末尾。谢谢
【解决方案3】:

不会抛出异常,因为这段代码甚至不会编译。

无论如何-几点:

  • 使用异常处理时,将更具体的异常放在不太具体的异常之前(因此InvalidOperationException 的捕获应该在Exception 的捕获之前)。
  • 捕捉Exception 通常没有多大用处。
  • 如果您捕获到异常,请对其进行处理。

你的意思可能是:

throw new InvalidOperationException();

但是,按照您构建异常的方式,catch(Exception x) 块会运行。

【讨论】:

    【解决方案4】:

    你应该写:

    class xxx
    {
        public void Test()
        {
            try
            {
              throw new InvalidoperationException(); 
            }
            catch(InvalidoperationException exception)
            {
                // Do smth with exception;
            }            
            catch(Exception exception)
            {
                throw; // Rethrows your exception;
            }
        } 
    }
    

    InvalidOperationException 继承自 Exceptioncatch 试图处理最具体的分支,所以catch (InvalidOperationException x) 会在这里执行。

    【讨论】:

    • 您还应该重新排序catch 块 - 匹配的第一个块将运行,而不是最具体的块(因为所有异常都继承自 Exception)。
    【解决方案5】:

    不。它不会编译。所以,生成哪个异常是毫无疑问的。

    你的代码应该是这样的:

    class xxx
    {
        public void Test()
        {
            try
            {
              throw new InvalidoperationException(); 
            }
            catch(InvalidoperationException exception)
            {
                // Something about InvalidOperationException;
            }            
            catch(Exception exception)
            {
                // Something about the Exception
            }
        } 
    }
    

    注意点:

    1. 首先编写更具体的异常类,因此我们在异常类之前编写InvalidOperationException。

    【讨论】:

      【解决方案6】:

      忽略编译问题....第一个匹配的异常块 (catch(Exception x)) 将获得异常。然后你忽略异常并且不重新抛出,所以异常会被外界看到。不过,这并不是一种好的做法……特别是,捕捉任意的Exception 并忽略它是有风险的——它可能是任何东西……它不一定是例外你以为是。

      【讨论】:

        【解决方案7】:

        好吧,代码不会编译,但我会忽略它...

        如果我只看这条线:

        throw new Exception(InvalidoperationException);
        

        首先,根据 MSDN,没有这样的构造函数。所以我假设你的意思是构造函数:Exception(String msg, Exception innerException)。意义: throw new Exception("blabla", InvalidoperationException);

        抛出的异常是 Exception 类型,而不是 InvalidOperationException。所以只有 catch(Exception x) 可以捕获它。

        如果您抛出InvalidoperationException,而不是您编写捕获顺序的方式,则异常类将被捕获首先。 捕获的顺序很重要。

        我能给你的最好建议就是自己尝试一下,看看会发生什么。

        【讨论】:

          猜你喜欢
          • 2011-01-22
          • 2016-06-02
          • 1970-01-01
          • 2010-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-17
          • 2011-09-25
          相关资源
          最近更新 更多