【问题标题】:Should I throw in current method or let the later method throw it我应该抛出当前方法还是让后面的方法抛出它
【发布时间】:2015-08-27 06:41:02
【问题描述】:

我在设计方面遇到了困难。
我不确定是否应该让稍后的方法抛出异常,或者是否应该自己抛出异常。
事情是:

异常的类型会根据被调用的方法而变化。在后面的方法中,它可能是 InvalidOperation,但在当前方法中,ArgumentException 可能更适合。

现在我应该真正执行所有检查以抛出正确类型的异常,还是应该让更深层次的方法抛出不正确类型的异常?

考虑一下:

private bool _canWaste = false;



/// <summary>
///    Runs around and wastes something.
/// </summary>
/// <exception cref="InvalidOperationException">
///     Thrown when <paramref name="CanPower"/> is false.
/// </exception>
public void Run(bool CanWaste) {
   _canWaste = CanWaste;
   // <- Should I check if we can waste and throw an ArgumentException here or 
   //    throw the 'wrong' type later in Waste?
   Waste();
}



/// <summary>
///    Wastes something.
/// </summary>
/// <exception cref="InvalidOperationException">
///     Thrown when we cannot waste.
/// </exception>
private void Waste() {
   if(!_canWaste) throw new InvalidOperationException("We cannot waste.");
   /* ... */
}

这是一个很容易完成的简单示例(没有意义)。
但是,当然,有些方法的评估要困难得多。

另一种选择是捕获异常并抛出正确类型的新异常。
但我想这会影响性能并在输出中记录一些不酷的东西。

【问题讨论】:

    标签: c# exception throw


    【解决方案1】:

    一般来说,你应该尽可能快地投掷。这样,您可以防止代码在可能导致重大问题的无效状态下执行(例如,由于过滤器不正确,您删除了所有记录而不是一条记录)。

    另外,如果你快速抛出,你可以确保调用者得到最有意义的消息。

    public void Run(bool CanWaste)
    {
        if(!CanWaste)
            throw new ArgumentException("CanWaste must be true", "CanWaste");
        Waste();
        // ...
    }
    

    但是,如果您不知道参数是否无效并且确定是否昂贵(例如,您需要执行它),那么让更深层的方法抛出。 您可以在调用方法中处理InvalidOperationException

    public void Run(bool CanWaste)
    {
        _canWaste = CanWaste;
    
        try
        {
            Waste();
        }catch(InvalidOperationException ioe)
        {
            throw new ArgumentException("CanWaste must be true", "CanWaste", ioe);
        }
    }
    

    当然,在这种情况下,很容易确定参数是否有效。这也不是最好的例子,因为只能是 truebool 参数没有多大意义。

    【讨论】:

    • 这就是让我困惑的地方。因为参数并不是真的无效,即使在当前方法中也是如此。这只是一些依赖于某个值的有效性的操作,这恰好是我的论点。但我想通知 arg 无效是有道理的。
    • @NoelWidmer: 但是你先调用Waste 不喜欢_canWaste == false,所以实际上它在这个方法中已经无效或者抛出一个不正确InvalidOperatonExceptionWaste.
    • 我猜你是对的。谢谢你帮我解决这个问题。
    【解决方案2】:

    不要抛出或让代码抛出不正确的类型异常,这对任何人都没有帮助。如果你得到一个无效的参数抛出InvalidArgumentException,否则让异常从库中冒泡到调用者。

    从描述中,听起来 您正试图通过异常来控制执行流程。不要那样做。例外就是“例外”,当出现无法避免的例外情况时使用它们。

    除非您想自己重置堆栈跟踪,否则捕获并重新抛出该异常是没有意义的。

    【讨论】:

    • 但是如果一个参数的正确性只能通过调用一个在参数无效时抛出异常的方法来验证。我应该抓住它并抛出一个无效参数异常吗?
    • @NoelWidmer,考虑一个更简单的例子,假设您正在获取DateTime 的字符串参数,该参数必须采用特定格式,当您尝试解析 string DateTime 使用DateTime.ParseExactDateTime 对象,你会得到一个无效的字符串格式异常,在这种情况下,你可以捕获解析过程中发生的异常并将InvalidArugmentException 返回给客户端。如果您的情况与此类似,那么当然,抓住InvalidOperationException,然后抛出InvalidArgumentException
    • 除了上面的 ^^,如果你的方法的唯一目的是验证参数,它应该被命名,并且可能返回一个布尔值来指示参数是否有效,而不是抛出例外,只是使意图更明确,代码更易读,IMO。
    • 这很有用,谢谢 :) 执行流程也是很好的提醒。请记住,这是一个“愚蠢”的例子,我并不是真的想做那样的事情。
    猜你喜欢
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    相关资源
    最近更新 更多