简体   繁体   English

如果无法发生异常,是否应该引发并处理异常?

[英]Should an exception be thrown and handled if it cannot happen?

I have a function that takes three parameters (day, month & year) and creates a new dateTime. 我有一个函数,需要三个参数(日,月和年)并创建一个新的dateTime。 It's a public function that gets called when any of three comboboxes are dropped down. 这是一个公共函数,当三个组合框中的任何一个下拉时,都将调用它。

When unit testing I accidentally entered an invalid value and it threw a invalid date time exception, but this won't be possible in the application as the comboboxes are pre-populated with valid values only. 当进行单元测试时,我不小心输入了一个无效值,并抛出了无效的日期时间异常,但这在应用程序中将无法实现,因为组合框仅预填充了有效值。

So question is should I still check and handle this exception in the function? 因此问题是我是否仍应在函数中检查并处理此异常?

In general, yes, any public function could be called from anywhere and it is good practice to defend your code from invalid inputs also if, at certain point in time, you are sure about who feeds the inputs to the function. 通常,是的,任何公共函数都可以在任何地方调用,并且如果在某个时间点您确定谁将输入提供给函数,那么也可以保护代码免受无效输入的侵害。

However, this supposed function could handle the impossible situations by itself without triggering an exception if the inputs are not good. 但是,如果输入不好,则该假定函数可以自行处理不可能的情况,而不会触发异常。

It is relatively easy to check the inputs and follow the well known pattern of TryParse 检查输入并遵循TryParse的众所周知的模式相对容易

 public bool TryMakeDateTime(int year, int month, int day, out DateTime date)
 {
      date = DateTime.MinValue;

      if(!IsValidDay(year, month, day))
        return false;

      date = new DateTime(year, month, day);
      return true;
 }

 public bool IsValidDay(int year, int month, int day)
 {
     if(day < 1 || day > 31)
        return false;

     if(month < 1 || month > 12)
        return false;

     if(day > 30 && (month == 2 ||
                     month == 4 || 
                     month == 6 || 
                     month == 9 || 
                     month == 11))
        return false;

     // This is arbitrary, adjust the check to your constraints
     if(year < 1900 || year > 2099)
         return false;

     if(month == 2)
     {
         // IsLeapYear cannot handle values below 1 or higher than 9999
         // but we have already checked the year with more retrictive
         // constraints.
         int extraDay = (DateTime.IsLeapYear(year) ? 1 : 0);
         if(day > (28 + extraDay))
             return false;
     }
     return true;
 }

Yes, the function should throw an exception for invalid inputs, if the function, in isolation, allows invalid inputs to be submitted. 是的,如果该函数单独允许提交无效输入,则该函数应为无效输入引发异常。 You don't know how, or from where, a future developer might call this function. 您不知道将来的开发人员如何或从何处调用此函数。 But another, better option is to code the function so that only valid inputs are allowed. 但是另一个更好的选择是对函数进行编码,以便仅允许有效输入。

You can do this by changing the type of the inputs from integer values to Enums. 您可以通过将输入类型从整数值更改为Enums来实现。 Create a Month Enum 创建一个月枚举

public enum CalendarMonth {
  NotSet = 0, January = 1, February = 2,
  March = 3, April = 4, May = 5, June = 6,
  July = 7, August = 8, September = 9,
  October = 10, November = 11, December = 12}

and a DayOfMonth Enum 和DayOfMonth枚举

public enum DayOfMonth {
  NotSet = 0, dom1 = 1, dom2 = 2, ....etc., ... dom31 = 31 }

You could code the function to treat the 31st of months with only 30 days in them as the first of the next month, and Feb 29, 30 and 31 as March 1,2,3, etc., to avoid treating this as invalid. 您可以将该函数编码为将只有30天的第31个月视为下个月的第一个月,并将2月29日,30和31视为3月1,2,3等,以免将其视为无效。 Then your function's signature would be 然后您的函数的签名将是

public DateTime NewDate(DayOfMonth dom, CalendarMonth month, int year);

and it would not be possible to pass it invalid values. 并且无法传递无效值。 (except I guess for year values outside the DateIme.MinDate to DateTime.MaxDate range) (除了我猜测DateIme.MinDateDateTime.MaxDate范围之外的年份值)

You should not prevent or catch the exception. 您不应阻止或捕获异常。 But you should make sure an exception will really happen in that "impossible" case. 但是您应该确保在这种“不可能”的情况下确实会发生异常。

Exceptions are meant for "impossible" situations that are thought not to occur "normally". 异常是指认为“不可能”发生的“不可能”情况。

If for example you call a DateTime constructor overload, that constructor will already throw an exception if the input is invalid. 例如,如果您调用DateTime构造函数重载,则如果输入无效,则该构造函数将已引发异常。 If you reason that will not happen in your situation, do not handle that case. 如果您认为这种情况不会发生,请不要处理这种情况。 The exception message generated by the framework is just fine. 框架生成的异常消息很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM