我应该抛出ArgumentException吗?

时间:2016-11-02 16:43:30

标签: c# .net exception msdn argumentexception

这个问题是关于约定和解释MSDN的,所以我不认为它主要是基于意见的。

我想知道ArgumentException:我有一个构建器类,用于构建一个过滤器对象,该对象将在从邮箱中检索一组电子邮件时应用。构建器有许多方法可以设置过滤器选项。例如,我有两种方法来设置"发送日期"过滤器的范围 - 在XX之前发送和/或在XX之后发送。我想为每个添加一个保护条款,如果提供"之前" 提供的""之后的日期是日期。我会用一种常见的验证方法来做到这一点:

/// <summary>
/// This class provides methods for validating dates in various ways.
/// </summary>
internal static class DateValidation
{
    /// <summary>
    /// Validate the provided "start" and "end" date/time values.
    /// If they do not represent a valid range, throw an exception.
    /// </summary>
    /// <param name="start">The date/time that represents the start of the range.</param>
    /// <param name="end">The date/time that represents the end of the range.</param>
    internal static void ValidateDateTimeRange(DateTime? start, DateTime? end)
    {
        if (start.HasValue && end.HasValue)
        {
            if (start.Value > end.Value) 
                throw new Exception(
                string.Format(@"The start date/time ""{0}"" " +
                @"occurs after the end date/time ""{1}"".", 
                start.ToString(), end.ToString()));
        }
    }
}

以下是两种构建器方法:

/// <summary>
/// Set a value which represents a date/time after which
/// messages must have been sent to be part of filtered output.
/// </summary>
/// <param name="afterDateTime">The date/time after which
/// messages must have been sent to be part of filtered output.</param>
public void SetSentAfterDateTime(DateTime afterDateTime)
{
    DateValidation.ValidateDateTimeRange(afterDateTime, _sentBeforeDateTime);
    _sentAfterDateTime = afterDateTime;
}

/// <summary>
/// Set a value which represents a date/time before which
/// messages must have been sent to be part of filtered output.
/// </summary>
/// <param name="beforeDateTime">The date/time before which
/// messages must have been sent to be part of filtered output.</param>    
public void SetSentBeforeDateTime(DateTime beforeDateTime)
{
    DateValidation.ValidateDateTimeRange(_sentAfterDateTime, beforeDateTime);
    _sentBeforeDateTime = beforeDateTime;
}

根据MSDN

  

最常见的是,公共语言抛出了ArgumentException   运行时或其他类库,表示开发人员错误。

我得到的短语&#34;最常见的&#34;为我的其他用途留下了开放的可能性,但我喜欢坚持惯例。我正在构建一个公共API,因此异常将被记录下来,并将超出公共接口;此外,它没有表明开发者错误&#34;。 可以可以想象地指示用户错误(使用异常来处理用户输入验证问题是一种常见的惯例)。但是,基于MSDN描述,我感觉这不是它的目的。

  

...派生类[ArgumentNullException和   应该使用ArgumentOutOfRangeException]代替   ArgumentException,除非在派生的情况下都没有   课程是可以接受的例如,应该抛出异常:

     

...

     

参数值在外面时的ArgumentOutOfRangeException   可接受值的范围;例如,当值&#34; 46&#34;是   在创建DateTime期间作为月参数传递。

我的参数可能超出了可接受值的范围,但该条件是根据其他日期/时间值动态确定的。没有静态范围的值超出范围&#34;。

ArgumentException通常用于这种情况吗?

2 个答案:

答案 0 :(得分:10)

我同意接受的答案;我想补充一点,如果你的代码将你的调用者放在必须捕获异常以确定用户提供的数据是否有效的位置,那么你已经做了我所谓的“烦恼”例外”。令人烦恼的是,您必须创建一个异常处理程序来处理非异常情况。输入不一致日期范围的用户不是例外。这是该计划工作流程的正常部分。

考虑在用户界面层中解决问题。实施日期选择器,以便它们不允许用户选择会产生异常的日期组合。有很多方法可以做到这一点 - 例如,灰色日期是无效的。或者检测不一致性并使拣选器变为红色或闪光等等,并防止操作被提交。

答案 1 :(得分:7)

来自Krzysztof Cwalina的How to Design Exception Hierarchies

  

通过更改调用例程的代码可以避免使用错误。

我们同意这是一个使用错误。

Eric Lippert称他们为Boneheaded exceptions

  

Boneheaded异常是你自己的错误,你可以阻止它们,因此它们是你代码中的错误。你不应该抓住它们;这样做会隐藏代码中的错误。

开发人员不应catch这些类型的错误,而是更改调用代码以确保首先不会发生异常。这就是为什么确切的异常类型并不重要。

Cwalina解释说:

  

需要将使用错误传达给调用例程的人类开发人员。异常类型不是向人类传达错误的最佳方式。消息字符串是一种更好的方法。因此,对于因使用错误而抛出的异常,我将专注于设计一个非常好的(即解释性)异常消息并使用现有的.NET Framework异常类型之一:ArgumentNullException,ArgumentException,InvalidOperationException,NotSupportedException等换句话说,不要为使用错误创建新的异常类型,因为异常的类型与使用错误无关。 .NET Framework已经有足够的类型(实际上太多,恕我直言)来表示我能想到的每个使用错误。

(强调我的)

您是否使用ArgumentExceptionInvalidOperationException并不重要。选择一个,但要确保它有一个明确的Message