2

我有以下方法:

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;
}

但是,代码合同建议我添加以下内容:

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第一个建议允许的情况。

有什么办法可以删除这些建议?

4

1 回答 1

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));
}
于 2013-09-05T23:18:42.453 回答