5

当我注意到来自我的 Visual Studio (2008) 内部的静态验证警告时,我只是在 Stack Overflow 上胡乱回答某人的问题:

string[] source = { "1", "A", "B" };
var sourceObjects = Array.ConvertAll(source, c => new Source(c)).ToArray();

我收到消息需要未经证实的来源!= null。在我看来,情况并非如此。这当然只是一个例子。另一方面,一些非常漂亮的东西似乎运作良好。

我正在使用 1.2.20518.12 版本(5 月 18 日)。我发现代码合同很有趣,但其他人有过这样的案例吗?您认为当前的实现在实践中是可用的,还是在这一点上认为它们纯粹是学术性的?

我已经把它变成了一个社区维基,但我想听听一些意见:)

4

1 回答 1

16

如果您将两个调用分开,则更有意义:

string[] source = { "1", "A", "B" };
var tmp = Array.ConvertAll(source, c => new Source(c));
var sourceObjects = tmp.ToArray();

现在它指向最后一行作为问题。换句话说,调用Array.ConvertAll知道源不为空,但调用ToArray()不知道源tmp不为空。

(由于在源代码中使用了名称,您的示例也有些令人困惑-即使您将变量称为完全不同的东西,source该错误仍然会使用,因为它指的是 . 中的第一个参数。)sourceEnumerable.ToArray

基本上,我相信当 Array.ConvertAll 获得适当的非空后置条件时,这一切都会奏效。在那之前,这将起到作用:

string[] source = { "1", "A", "B" };
var tmp = Array.ConvertAll(source, c => new Source(c));
Contract.Assume(tmp != null);
var sourceObjects = tmp.ToArray();

我同意这种事情很烦人,但我相信随着 MS 在 BCL 中添加越来越多的合同,它会迅速改善。需要注意的是,静态检查器本身没有问题。

(事实上​​,Array.ConvertAll也没有前置条件 - 如果您source在上面的第二个代码片段中将变量设置为 null,它仍然不会抱怨。)

于 2009-08-09T12:18:27.043 回答