.NET代码契约:它能比这更基本吗?

时间:2009-08-09 11:50:17

标签: c# .net code-contracts microsoft-contracts

当我在Visual Studio(2008)内部发现静态验证警告时,我只是在堆栈溢出中回答某人的问题:

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

我收到消息需要未经证实的来源!= null 。我觉得很明显,事实并非如此。这只是一个例子。另一方面,一些漂亮的东西似乎运作得相当好。

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

我已将其设为社区维基,但我想听听一些意见:)

1 个答案:

答案 0 :(得分:16)

如果你分开两个电话会更有意义:

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

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

(由于在您的源代码中使用了名称source,您的示例也有些混乱 - 即使您将变量调用完全不同,错误仍会使用source,如它指的是Enumerable.ToArray中的第一个参数。)

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

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,它仍然不会抱怨。)