以下代码在前置条件下失败。这是代码契约中的一个bug吗?
static class Program
{
static void Main()
{
foreach (var s in Test(3))
{
Console.WriteLine(s);
}
}
static IEnumerable<int>Test (int i)
{
Contract.Requires(i > 0);
for (int j = 0; j < i; j++)
yield return j;
}
}发布于 2009-07-02 02:46:36
我的猜测是这与迭代器的延迟特性有关。请记住,协定处理将在最终发出的IL上发生,而不是在C#代码上。这意味着您必须考虑为迭代器和lambda表达式等功能生成的代码。
如果你反编译这些代码,你会发现"i“实际上不是一个参数。它将是用于实现迭代器的类中的一个变量。因此,代码实际上看起来更像下面这样
class IteratorImpl {
private int i;
public bool MoveNext() {
Contract.Require(i >0);
..
}
}我对契约API不是很熟悉,但我猜生成的代码更难验证。
发布于 2009-07-02 02:49:57
请记住,迭代器只有在枚举之后才会运行,并在后端编译成某种特殊的调味品。如果您想要验证参数,您应该遵循的一般模式是拥有一个包装器函数:
static IEnumerable<int> Test (int i)
{
Contract.Requires(i > 0);
return _Test(i);
}
private static IEnumerable<int> _Test (int i)
{
for (int j = 0; j < i; j++)
yield return j;
}这样,Test()将在被调用时检查参数,然后返回_Test(),这实际上只是返回一个新类。
发布于 2009-07-02 02:50:50
这里有一个关于单元测试、迭代器、延迟执行和你的主题的blog post。
延迟执行是这里的问题。
https://stackoverflow.com/questions/1072184
复制相似问题