为什么可以为后置条件和对象不变量添加和删除代码契约,而不能为C#中的前置条件添加和删除代码契约?
为什么可以为后置条件和对象不变量添加和删除代码契约,而不能为C#中的前置条件添加和删除代码契约 在CLR via C#一书中,我遇到了以下摘录: 而且,由于合同不能对新版本更加严格(不破坏兼容性),您需要 在引入新的虚拟、抽象或接口成员时,应仔细考虑先决条件。 对于后置条件和对象不变量,可以根据条件随意添加和删除契约 表示在虚/抽象/接口成员中,条件表示在重写 成员仅在逻辑上被合并在一起 这让我非常困惑,后置条件和对象不变量,契约可以随意添加和删除。我希望有人建议,后置条件和对象不变量只能变得更严格,前提也更严格。我为什么期待这个?因为我可以举一个例子,证明这个建议是错误的。例如 起初我们有一个后置条件,一切正常:为什么可以为后置条件和对象不变量添加和删除代码契约,而不能为C#中的前置条件添加和删除代码契约?,c#,code-contracts,C#,Code Contracts,为什么可以为后置条件和对象不变量添加和删除代码契约,而不能为C#中的前置条件添加和删除代码契约 在CLR via C#一书中,我遇到了以下摘录: 而且,由于合同不能对新版本更加严格(不破坏兼容性),您需要 在引入新的虚拟、抽象或接口成员时,应仔细考虑先决条件。 对于后置条件和对象不变量,可以根据条件随意添加和删除契约 表示在虚/抽象/接口成员中,条件表示在重写 成员仅在逻辑上被合并在一起 这让我非常困惑,后置条件和对象不变量,契约可以随意添加和删除。我希望有人建议,后置条件和对象不变量只能变得更
using System.Diagnostics.Contracts;
public sealed class Program
{
public static void FooBaseContract(int i)
{
Contract.Ensures(i > 0);
}
}
public class FooBase
{
public virtual int i
{
get {return 2;}
}
}
public class FooDerived : FooBase
{
public override int i
{
get {return 4;}
}
}
现在,我们决定使后处理条件更加严格:
using System.Diagnostics.Contracts;
public sealed class Program
{
public static void FooBaseContract(int i)
{
Contract.Ensures(i > 4);
}
}
public class FooBase
{
public virtual int i
{
get {return 2;}
}
}
public class FooDerived : FooBase
{
public override int i
{
get {return 4;}
}
}
这肯定会使使用前一后置条件的代码与新后置条件不兼容。这意味着我们通过使后置条件更加严格而失去了向后兼容性
此外,我不明白作者为什么只引用虚拟、抽象或接口成员
。因为在我上面给出的人为示例中,即使我将代码更改为以下内容(删除所有虚拟、抽象或接口成员
),也会出现与新代码契约版本不兼容的情况:
那么,有人能简单地解释一下我在这里遗漏了什么吗
更新
正如评论部分所提到的,代码契约是一个不推荐使用的概念。这对我来说没关系,我只是想理解这个想法-在这种情况下,这就是为什么我们可以使后置条件和对象不变量更严格?这与我的常识相矛盾,这意味着以前允许返回某些内容(或对象不变量发生),现在我们声明不再允许返回某些内容,本书作者告诉我,这种情况并没有破坏向后兼容性。文本中说,条件是“and”在一起这意味着您根本没有删除后置条件和不变量的能力。无论如何编写代码,都只能添加它们 后置条件和不变量是在退出时必须确保的东西。能够增加义务是有道理的。如果您正在添加矛盾,CC应将其标记为后条件冲突
从兼容性和可扩展性的角度来看,基类的用户将得到他们期望的保证。他们可能会得到他们不知道或不关心的额外保证。评论不用于进一步讨论;这段对话已经结束。
using System.Diagnostics.Contracts;
public sealed class Program
{
public static void FooBaseContract(int i)
{
Contract.Ensures(i > 4);
}
}
public class FooBase
{
public int i
{
get {return 2;}
}
}