C#:代码合同与正常参数验证

ste*_*eee 32 .net c# .net-4.0 code-contracts microsoft-contracts

考虑以下两段代码:

    public static Time Parse(string value)
    {
        string regXExpres = 
           "^([0-9]|[0-1][0-9]|2[0-3]):([0-9]|[0-5][0-9])$|^24:(0|00)$";
        Contract.Requires(value != null);
        Contract.Requires(new Regex(regXExpres).IsMatch(value));
        string[] tokens = value.Split(':');
        int hour = Convert.ToInt32(tokens[0], CultureInfo.InvariantCulture);
        int minute = Convert.ToInt32(tokens[1], CultureInfo.InvariantCulture);
        return new Time(hour, minute);
    }
Run Code Online (Sandbox Code Playgroud)

    public static Time Parse(string value)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }
        string[] tokens = value.Split(':');
        if (tokens.Length != 2)
        {
            throw new FormatException("value must be h:m");
        }
        int hour = Convert.ToInt32(tokens[0], CultureInfo.InvariantCulture);
        if (!(0 <= hour && hour <= 24))
        {
            throw new FormatException("hour must be between 0 and 24");
        }
        int minute = Convert.ToInt32(tokens[1], CultureInfo.InvariantCulture);
        if (!(0 <= minute && minute <= 59))
        {
            throw new FormatException("minute must be between 0 and 59");
        }
        return new Time(hour, minute);
    }
Run Code Online (Sandbox Code Playgroud)

我个人更喜欢第一个版本,因为代码更清晰,更小,并且可以轻松关闭合同.但缺点是Visual Studio Code Analysis指责我应该检查null的参数值,并且构造函数的Contracts没有意识到正则表达式确保分钟和小时在给定的boundarys内.

所以我最终得到了很多错误的警告,我认为无法通过合同验证字符串值,而不会抛出除RegEx验证之外的FormatExceptions.

有关如何使用Code契约解决此问题和等效情况的任何建议?

Dzm*_*uba 21

为了摆脱警告,你可以使用Contract.Assume

  • @steveee,你应该总是在连词上拆分合约,这样`Contract.Assume(0 <=小时&&小时<= 24);`变成`Contract.Assume(0 <=小时); Contract.Assume(小时<= 24);` (15认同)
  • @ssg:我不认为它在文档中,但是如果你搜索Code Contracts MSDN论坛,那里有来自开发者的信息,例如:"将连词分成不同的契约会使静态检查器更加精确,你会得到更好的错误信息. " (3认同)