C# 代码契约静态分析器不会检测到微不足道的契约违反

C# 代码契约静态分析器不会检测到微不足道的契约违反,c#,static-analysis,code-contracts,C#,Static Analysis,Code Contracts,我有以下代码: using System; using System.Diagnostics.Contracts; namespace TestCodeContracts { class Program { public static int Divide(int numerator, int denominator, out int remainder) { Contract.Requires<ArgumentEx

我有以下代码:

using System;
using System.Diagnostics.Contracts;

namespace TestCodeContracts
{
    class Program
    {
        public static int Divide(int numerator, int denominator, out int remainder)
        {
            Contract.Requires<ArgumentException>(denominator != 0);
            Contract.Requires<ArgumentException>(numerator != int.MinValue || denominator != -1, "Overflow");
            Contract.Ensures(Contract.Result<int>() == numerator / denominator);
            Contract.Ensures(Contract.ValueAtReturn<int>(out remainder) == numerator % denominator);

            remainder = numerator % denominator;
            return numerator / denominator;
        }

        static void Main(string[] args)
        {
            int remainder;
            Console.WriteLine(Divide(10, 6, out remainder));
            Console.WriteLine(Divide(5, remainder, out remainder));

            Console.WriteLine(Divide(3, 0, out remainder));

            Console.Read();
        }
    }
}
在第一个Divide调用中,如果我将6替换为0,那么静态分析会正确地发出警告

如果我将6替换为5,则在第二次Divide调用中正确地得到警告

然而,不管怎样,我在第三次通话中从未收到任何警告。相反,我只是得到一个运行时错误

为什么静态分析器无法检测到第三行违反了合同


我使用的是64位Windows 8上的Visual Studio 2012。代码契约是Microsoft code contracts devlabs_TS 1.4.51019.0 for.NET,它似乎是截至2012年12月的最新版本。

这是一个有趣的问题

我最终将划分简化为:

public static int Divide(int numerator, int denominator)
{
    Contract.Requires<ArgumentException>(denominator != 0);
    return numerator / denominator;
}
请注意,我发现即使只有一个项目,您通常也必须重建而不是构建。必须有代码契约人工制品在重建时得到清理

这不会引发警告:

static void Main(string[] args)
{
    Console.WriteLine(Divide(10, 9));
    Console.WriteLine(Divide(10, 0));
}
我唯一能触发警告的方法是,如果第一个除法的分母是10,那么当它是0时,它显然也起作用


这看起来确实像一个bug——我会给代码合同团队发一封电子邮件,看看他们怎么说。

这是一个有趣的问题

我最终将划分简化为:

public static int Divide(int numerator, int denominator)
{
    Contract.Requires<ArgumentException>(denominator != 0);
    return numerator / denominator;
}
请注意,我发现即使只有一个项目,您通常也必须重建而不是构建。必须有代码契约人工制品在重建时得到清理

这不会引发警告:

static void Main(string[] args)
{
    Console.WriteLine(Divide(10, 9));
    Console.WriteLine(Divide(10, 0));
}
我唯一能触发警告的方法是,如果第一个除法的分母是10,那么当它是0时,它显然也起作用

这看起来确实像一个bug——我会给代码合同团队发一封电子邮件,看看他们怎么说。

我发布了。已经确认这确实是一个bug,并且它将被修复

错误在于静态验证器认为Divide3,0。。。遥不可及

我们将修复这个错误

我贴了。已经确认这确实是一个bug,并且它将被修复

错误在于静态验证器认为Divide3,0。。。遥不可及

我们将修复这个错误


你检查得很彻底吗?中间有重建吗?设置更多的测试调用可能比“将6改为0”更好。@HenkHolterman重建不会改变我的结果。此外,如果我在三个测试函数Test1、Test2和Test3中的第一个Divide调用中分离出我的三个cases6、5和0,然后调用这三个测试函数,我只在其中两个测试函数中得到警告-每个测试函数的第三个Divide调用从未得到警告,尽管这显然违反了合同。你仔细检查了吗?中间有重建吗?设置更多的测试调用可能比“将6改为0”更好。@HenkHolterman重建不会改变我的结果。此外,如果我在三个测试函数Test1、Test2和Test3中的第一个Divide调用中分离出我的三个cases6、5和0,然后调用这三个测试函数,我只在其中两个测试函数中得到警告-每个测试函数的第三个Divide调用从未得到警告,尽管这显然违反了合同,但你说的重建而不是建造是什么意思。你的意思是你必须让它正常工作,还是你必须复制这种行为?我无法为第10、9分区复制此信息-在这种情况下,我仍然得到警告。不管怎样,我都没有发过邮件,但我把它贴在了他们的论坛上——我必须重新构建代码契约才能正常工作。你说的“必须重新构建而不是构建”是什么意思。你的意思是你必须让它正常工作,还是你必须复制这种行为?我无法为第10、9分区复制此信息-在这种情况下,我仍然得到警告。不管怎样,我都没有发过电子邮件,但我把它贴在了他们的论坛上——为了让代码契约正常工作,我不得不重新构建。