我有以下方法:
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
。
有没有办法删除这些建议?
答案 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));
}