C# 代码契约:IEnumerable.Min上的静态检查失败
我在下面包含代码契约的代码中得到一些警告C# 代码契约:IEnumerable.Min上的静态检查失败,c#,code-contracts,C#,Code Contracts,我在下面包含代码契约的代码中得到一些警告 public static int Min(IEnumerable<int> set) { Contract.Requires(set != null); Contract.Requires(set.Any()); Contract.Ensures(Contract.ForAll(set, x => x >= Contract.Result<int>())); int min = s
public static int Min(IEnumerable<int> set)
{
Contract.Requires(set != null);
Contract.Requires(set.Any());
Contract.Ensures(Contract.ForAll(set, x => x >= Contract.Result<int>()));
int min = set.Min();
return min;
}
static void Main(string[] args)
{
Console.WriteLine(Min(new int[] {3,4,5}));
Console.WriteLine(Min(new int[] {})); // should fail
}
publicstaticintmin(IEnumerable集合)
{
Contract.Requires(set!=null);
Contract.Requires(set.Any());
Contract.survey(Contract.ForAll(set,x=>x>=Contract.Result());
int min=set.min();
返回最小值;
}
静态void Main(字符串[]参数)
{
Console.WriteLine(Min(新的int[]{3,4,5}));
WriteLine(Min(new int[]{}));//应该失败
}
我收到以下警告:
Requires unproven: set.Any() on Min(new int[] {3,4,5})
Ensures unproven: Contract.ForAll(set, x => x > Contract.Result<int>())
public static int Min(List<int> set)
{
Contract.Requires(set != null);
Contract.Requires(set.Count>0);
Contract.Ensures(Contract.ForAll(set, x => x >= Contract.Result<int>()));
int min = set.Min();
return min;
}
static void Main(string[] args)
{
Console.WriteLine(Min(new List<int> { })); // should fail
Console.WriteLine(Min(new List<int> { 3, 4, 5 }));
Console.ReadKey();
}
要求在Min(new int[]{3,4,5})上使用未经验证的:set.Any()
确保未经验证:Contract.ForAll(set,x=>x>Contract.Result())
两个问题:
提前谢谢。首先,
确保
子句对所有的IEnumerable
无效。您可以编写一个IEnumerable
,第一次枚举时返回一个序列(例如1、2、3
),第二次返回另一个列表(例如0
)。它是一个具有任意实现的接口
IEnumerable
通常有很多(潜在生成的)东西在幕后进行。我不认为CC能看穿这一点,即使具体的运行时类型不知何故是已知的
CC甚至能够对IEnumerable
进行启发式推理吗?这对我来说是新鲜事。它必须假设一个序列在多次枚举时不会改变(在数据库查询的情况下这是非常错误的)
让我指出,作为主观方面的注意,我发现CC检查器太过有限,没有任何用处。它会给证明有趣的属性带来极大的麻烦。它不能很好地处理抽象。这个
子句确保了
子句并非对所有IEnumerable
都有效。您可以编写一个IEnumerable
,第一次枚举时返回一个序列(例如1、2、3
),第二次返回另一个列表(例如0
)。它是一个具有任意实现的接口
IEnumerable
通常有很多(潜在生成的)东西在幕后进行。我不认为CC能看穿这一点,即使具体的运行时类型不知何故是已知的
CC甚至能够对IEnumerable
进行启发式推理吗?这对我来说是新鲜事。它必须假设一个序列在多次枚举时不会改变(在数据库查询的情况下这是非常错误的)
让我指出,作为主观方面的注意,我发现CC检查器太过有限,没有任何用处。它会给证明有趣的属性带来极大的麻烦。它不能很好地处理抽象。静态代码检查器无法确定该集合包含任何数据。如果您仔细想想,检查器不知道各种方法和属性的作用,除非一些契约是在方法本身内部定义的 在您的例子中,检查程序不知道扩展方法Any()或Min()的结果,因此无法验证任何要求和保证 通过更改参数的类型,您可以得到较少的警告,但最终代码检查器仍然无法确保您的代码能够满足Min(…)的要求 如果将类型更改为int[]或List,某些警告可能会消失。以下代码不返回任何警告:
Requires unproven: set.Any() on Min(new int[] {3,4,5})
Ensures unproven: Contract.ForAll(set, x => x > Contract.Result<int>())
public static int Min(List<int> set)
{
Contract.Requires(set != null);
Contract.Requires(set.Count>0);
Contract.Ensures(Contract.ForAll(set, x => x >= Contract.Result<int>()));
int min = set.Min();
return min;
}
static void Main(string[] args)
{
Console.WriteLine(Min(new List<int> { })); // should fail
Console.WriteLine(Min(new List<int> { 3, 4, 5 }));
Console.ReadKey();
}
public static int Min(列表集)
{
Contract.Requires(set!=null);
合同要求(集合计数>0);
Contract.survey(Contract.ForAll(set,x=>x>=Contract.Result());
int min=set.min();
返回最小值;
}
静态void Main(字符串[]参数)
{
WriteLine(Min(新列表{}));//应该失败
WriteLine(Min(新列表{3,4,5}));
Console.ReadKey();
}
当然,如果您运行此代码,它将失败并出现异常,因此代码检查器可能足够聪明,能够检测到这一点
如果您保持原来的顺序,您仍然会收到警告:
Console.WriteLine(Min(new List<int> { 3, 4, 5 }));
Console.WriteLine(Min(new List<int> { })); // should fail
Console.WriteLine(Min(新列表{3,4,5}));
Console.WriteLine(Min(新列表{}));//应该失败
在这两种情况下,您也会得到一些疯狂的建议,比如在Main()中添加Contract.surveures(false)。静态代码检查器无法确定该集合包含任何数据。如果您仔细想想,检查器不知道各种方法和属性的作用,除非一些契约是在方法本身内部定义的 在您的例子中,检查程序不知道扩展方法Any()或Min()的结果,因此无法验证任何要求和保证 通过更改参数的类型,您可以得到较少的警告,但最终代码检查器仍然无法确保您的代码能够满足Min(…)的要求 如果将类型更改为int[]或List,某些警告可能会消失。以下代码不返回任何警告:
Requires unproven: set.Any() on Min(new int[] {3,4,5})
Ensures unproven: Contract.ForAll(set, x => x > Contract.Result<int>())
public static int Min(List<int> set)
{
Contract.Requires(set != null);
Contract.Requires(set.Count>0);
Contract.Ensures(Contract.ForAll(set, x => x >= Contract.Result<int>()));
int min = set.Min();
return min;
}
static void Main(string[] args)
{
Console.WriteLine(Min(new List<int> { })); // should fail
Console.WriteLine(Min(new List<int> { 3, 4, 5 }));
Console.ReadKey();
}
public static int Min(列表集)
{
Contract.Requires(set!=null);
合同要求(集合计数>0);
Contract.survey(Contract.ForAll(set,x=>x>=Contract.Result());
int min=set.min();
返回最小值;
}
静态void Main(字符串[]参数)
{
WriteLine(Min(新列表{}));//应该失败
WriteLine(Min(新列表{3,4,5}));
Console.ReadKey();
}
当然,如果您运行此代码,它将失败并出现异常,因此代码检查器可能足够聪明,能够检测到这一点
如果您保持原来的顺序,您仍然会收到警告:<