【问题标题】:Blindly call functions, catch and deal with exceptions or write code to prevent the execution of a function that would throw an exception盲目调用函数,捕获并处理异常或编写代码以防止执行会抛出异常的函数
【发布时间】:2014-10-11 07:39:54
【问题描述】:

所以我想知道在处理代码中可能抛出的异常时,更好的做法是什么。

例如,我有一个项目列表。我是否应该在尝试访问之前检查“i”处的元素是否存在? (如果 list.Count > i),还是应该让代码执行,如果抛出异常则捕获异常?

我一直在做前者,我会编写检查以确保如果我知道它会抛出异常,函数不会被调用。 (边界检查、空值检查等)。但是现在我真的想起来了,我不只是在代码上加倍吗? List 类已经为我进行了边界检查,并引发了适当的异常。为什么我也要做边界检查?我可以省去自己的工作,盲目地调用函数,捕获异常并采取相应的行动。

哪种方式“更正确”?

【问题讨论】:

  • 异常处理总是很昂贵的。所以最好主动检查一些条件,避免调用/执行可能导致异常的任务。但是,如果你开始检查每一件事,你最终会得到一大块代码只做各种检查,这可能很难维护/阅读。如果有任何“正确”的方式来处理这种情况,即使我也想知道:-)

标签: c# exception


【解决方案1】:

这取决于您是否有处理没有元素i 的情况的好方法。

如果您没有一种对您的案例有意义的好方法来处理它,或者如果您真的不希望这种情况发生,请不要围绕它编写额外的代码,让它失败。如果你编写了好的测试,这些将为你需要处理和不需要处理的情况指明方向。

一些处理示例

您可能想要使用默认值,因为如果那里什么都没有,这可能并不重要,这是一个常见的、预期的和已处理的情况:

public Item GetItem(int i)
{
  if(list.Count>i)
    return list[i];
  else
    return null; //default value, could be an Item if that makes sense, see Null Object Pattern
}

或者,如果您需要在某个地方捕获它,您可能希望抛出一个更有意义的自定义异常(但不要将异常用于正常程序流程,它应该是一个例外情况):

public Item GetItem(int i)
{
  if(list.Count>i)
    return list[i];
  else
    throw new NoItemException();
}

或者,您可能只想为您或用户/支持人员设置更有意义的异常消息:

public Item GetItem(int i)
{
  if(list.Count>i)
    return list[i];
  else
    throw new Exception("There was no element found in the list of X at " + i);
}

【讨论】:

  • 在您的第一个示例中,仅执行一次 try catch 并在 catch 时返回 null 怎么样。 List 会为您进行边界检查并引发异常。
  • 你可以,但我只会在万不得已的情况下这样做。主要是因为我必须查找要捕获的异常类型,因为我不想全部捕获。
【解决方案2】:

我的观点是exceptions应该只在exception情况下抛出,其他情况应该通过本地错误检查来处理。

如何判断一个案例是否异常?这实际上归结为您的代码的假设(应该记录在案)。

如果您的代码假设当有人明确向它请求索引i 处的元素时,他必须确保该索引处存在一个元素(顺便说一句,这是一个非常合理的假设),那么如果索引 i 不存在,它应该抛出异常,因为这确实不应该发生并且被认为是异常的。

将其与有人要求您的代码返回值为“Foo”的元素进行比较。在这里,假设您的代码必须存在这样的元素是不合理的(因为调用者确实在查询,而不知道您的内部实现细节,ie 索引),如果找不到该元素,那就是根本不被视为异常,因此您不会抛出异常,而是返回 null。

如果有疑问,最好在错误检查方面犯错而不是抛出异常,因为处理异常的成本相对较高,需要数百 时钟周期,它们会破坏程序控制流,增加其复杂性。

【讨论】:

    【解决方案3】:

    我是否应该让代码执行,并在异常发生时捕获异常 扔了?

    不,一点也不,这就是Abusing Exception Handling。当您已经知道可能会出现可以修复或检查的问题时;那么为什么不先进行验证,而是将其包裹在 try .. catch 构造周围。

    例如,您可以执行以下操作

    Console.WriteLine("Please enter a number");
    try
    {
    int num = Convert.ToInt32(Console.ReadLine());
    }
    //if someone enter a `string` in place of Integer, it will cause
    catch(InvalidFormatException ix) 
    {
    }
    catch(Exception ex)
    {
    }
    

    这可以通过检查和使用TryParse() 之类的方法轻松避免

    Console.WriteLine("Please enter a number");
    int num;
    if (int.TryParse(Console.ReadLine(), out num))
     {
    
     }
    else
     {
       Console.WriteLine("Not a valid integer number");
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-25
      • 1970-01-01
      • 2021-06-29
      • 2013-10-16
      • 2015-10-13
      相关资源
      最近更新 更多