多余的代码合同建议

时间:2013-09-03 18:09:52

标签: c# code-contracts

我有以下方法:

static bool TextEquals(string text, char[] array, int start, int length)
{
    Contract.Requires(text != null);
    Contract.Requires(text.Length != length
                      || text.Length == 0
                      || (array != null && start >= 0 && start < array.Length));

    if (text.Length != length)
    {
        return false;
    }

    for (var i = 0; i < text.Length; ++i)
    {
        if (text[i] != array[start + i])
        {
            return false;
        }
    }

    return true;
}

但是,Code Contracts建议我添加以下内容:

Contracts.Requires(text.Length == 0 || array != null || start < array.Length);
Contracts.Requires(text.Length == 0 || start < 0 || start < array.Length);

我没有看到这两个额外要求的额外好处。已经存在的要求未涵盖哪些路径?

特别是,我没有看到第一个建议允许的案例array == null && start < array.Length

有没有办法删除这些建议?

1 个答案:

答案 0 :(得分:3)

我不太确定新建议试图涵盖哪些情况,但这似乎是静态分析器在您的ORed子句中遇到困难的结果。

保持Contract.Requires表达式尽可能简单是一个好主意,既可以帮助静态分析器,又可以使人类读者更容易。

在此示例中,以下Requires子句集不会引起任何其他建议:

Contract.Requires(text != null);
Contract.Requires(array != null);
Contract.Requires(start >= 0);
Contract.Requires(start <= array.Length - length);
Contract.Requires(length >= 0);

这些比你的原件更严格,但对于来电者来说似乎并不合理。

特别注意,需要start <= array.Length - length来防止array[start + i]上的数组溢出;原始条件start < array.Length是不够的,可能是您问题的根源。

顺便说一句,如果您愿意使用LINQ,您可以更简洁地重写此方法,如下所示:

static bool TextEquals2(string text, char[] array, int start, int length)
{
    Contract.Requires(text != null);
    Contract.Requires(array != null);
    Contract.Requires(start >= 0);
    Contract.Requires(length >= 0);

    return text.SequenceEqual(array.Skip(start).Take(length));
}