简体   繁体   English

CodeContracts:数组访问可能超出上限

[英]CodeContracts: Array access might be above the upper bound

I'm getting these warnings from CodeContracts: 我从CodeContracts得到这些警告:

Array access might be above the upper bound. 数组访问可能超出上限。 Did you meant 0 instead of 1? 您的意思是0而不是1?
Array access might be above the upper bound. 数组访问可能超出上限。 Did you meant 1 instead of 2? 您的意思是1而不是2?
Array access might be above the upper bound. 数组访问可能超出上限。 Did you meant 2 instead of 3? 您是说2而不是3吗?
Array access might be above the upper bound. 数组访问可能超出上限。 Did you meant 3 instead of 4? 您的意思是3而不是4?

On this line of code: 在这行代码中:

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

How do I tell the Contracts analyzer that these indices are guaranteed inside bounds? 如何告诉合同分析器这些指数在范围之内? _addr is initialized in the constructor to string[4] . _addr在构造函数中初始化为string[4]

I was able to get rid of these warnings by adding a method to that class that defined the invariants: 通过向定义不变式的类添加方法,我可以摆脱这些警告:

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

However, I think there's also a bug in your code. 但是,我认为您的代码中也存在一个错误。

If _addr[0] == null and _addr[1] != null , then AddressLine1 and AddressLine2 return the same value. 如果_addr[0] == null_addr[1] != null ,则AddressLine1AddressLine2返回相同的值。 This seems like a bug. 这似乎是一个错误。

You can fix this easily enough (and remove the need to specify contract invariants) by using something along the lines of what @ryanyuyu mentioned: 您可以通过使用@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();
    }
}

ContractInvariantMethod works when _addr is a class member. 当_addr是类成员时, ContractInvariantMethod起作用。 But Contract.Assert() works with local variables too. 但是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];
}

I don't know about the Contracts analyzer, but your code could be cleaner. 我不了解Contracts分析器,但是您的代码可能更简洁。 You are basically repeating code that just finds the first non-null string (and if the last element is null, you are returning that regardless). 您基本上是在重复只查找第一个非null字符串的代码(并且如果最后一个元素为null,则无论如何都将返回它)。 I'm a fan of using LINQ .FirstOrDefault which will let you find the first element that matches a condition (in your case not null). 我喜欢使用LINQ .FirstOrDefault ,它将使您找到与条件匹配的第一个元素(在您的情况下不为null)。 If no such element is found, it returns the default value (for a String it's null ) 如果找不到这样的元素,则返回默认值(对于String,它为null

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

See it in action at this .NET Fiddle . 在此.NET Fiddle中实际操作它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM