CodeContracts:数组访问可能高于上限

时间:2015-04-10 22:16:17

标签: c# code-contracts

我从CodeContracts收到这些警告:

  

数组访问可能高于上限。你的意思是0而不是1吗?   数组访问可能高于上限。你的意思是1而不是2吗?   数组访问可能高于上限。你的意思是2而不是3吗?   数组访问可能高于上限。你的意思是3而不是4?

在这行代码中:

private readonly string[] _addr;

public string AddressLine1
{
    get
    {
        return _addr[0] ?? _addr[1] ?? _addr[2] ?? _addr[3];
    }
}

public string AddressLine2
{
    get
    {
        return _addr[1] ?? _addr[2] ?? _addr[3];
    }
}

public string AddressLine3
{
    get
    {
        return _addr[2] ?? _addr[3];
    }
}

如何告知Contracts分析仪这些指数是否在边界内得到保证? _addr在构造函数中初始化为string[4]

3 个答案:

答案 0 :(得分:4)

通过向定义不变量的类添加方法,我能够摆脱这些警告:

[ContractInvariantMethod]
private void AddressInvariants()
{
    Contract.Invariant(_addr.Length == 4);
}

但是,我认为您的代码中也存在错误。

如果_addr[0] == null_addr[1] != null,则AddressLine1AddressLine2会返回相同的值。这似乎是一个错误。

您可以通过使用@ryanyuyu所提及的内容来轻松解决这个问题(并且无需指定契约不变量):

public string AddressLine1
{
    get
    {
        // Use the first non-null element.
        return _addr.Where(x => x != null).FirstOrDefault();
    }
}

public string AddressLine2
{
    get
    {
        // Use the second non-null element.
        return _addr.Where(x => x != null).Skip(1).FirstOrDefault();
    }
}

public string AddressLine3
{
    get
    {
        // Use the third non-null element.
        return _addr.Where(x => x != null).Skip(2).FirstOrDefault();
    }
}

答案 1 :(得分:0)

当_addr是类成员时,

ContractInvariantMethod有效。但Contract.Assert()也适用于局部变量。

static void MyParse(string foo)
{
    string[] split = foo.Split(',');
    Contract.Assert(split.Length == 4);

    string a = split[0];
    string b = split[1];
    string c = split[2];
    string d = split[3];
}

答案 2 :(得分:-1)

我不了解Contracts分析器,但您的代码可能更清晰。您基本上重复只找到第一个非空字符串的代码(如果最后一个元素为null,则无论如何都要返回)。我是使用LINQ .FirstOrDefault的粉丝,它可以让你找到匹配条件的第一个元素(在你的情况下不是null)。如果没有找到这样的元素,它将返回默认值(对于一个字符串,它是null

return _addr.FirstOrDefault(str => str != null);

请参阅此.NET Fiddle