[英]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
,则AddressLine1
和AddressLine2
返回相同的值。 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.