提问人:qqqqqqq 提问时间:2/21/2020 最后编辑:qqqqqqq 更新时间:2/21/2020 访问量:131
为什么可以为后置条件和对象不变量添加和删除代码协定,而不能为 C# 中的前提条件添加和删除代码协定?
Why code contracts can be added and removed for postconditions and object invariants, but not for preconditions in C#?
问:
为什么可以为后置条件和对象不变量添加和删除代码协定,而不能为 C# 中的前提条件添加和删除代码协定?
在《CLR via C#》一书中,我看到了以下摘录:
而且,由于新版本无法使合同更严格(不破坏兼容性),因此您 在引入新的虚拟、抽象或接口成员时,应仔细考虑前提条件。对于后置条件和对象不变量,可以随意添加和删除合约作为条件 在 virtual/abstract/interface 成员中表示,在重写中表示条件 成员只是在逻辑上 AND-ed 在一起。
这让我非常困惑,后置条件和对象不变量,合约可以随意添加和删除。我期望有人建议后置条件和对象不变量只会变得更严格,前提条件也会变得更严格。我为什么期待这个?因为我可以举出一个例子,说明这个建议被证明是错误的。例如
起初我们有一个后置条件,一切正常:
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;}
}
}
这肯定会使使用前一个后置条件的代码与新后置条件不兼容。这意味着我们通过使后置条件更严格而失去了向后兼容性。
另外,我不明白为什么作者只提到.因为在我上面给出的人为示例中,即使我将代码更改为以下内容(全部删除),也会发生与新代码合约版本不兼容的情况:virtual, abstract, or interface member
virtual, abstract, or interface member
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;}
}
}
那么,有人可以以万无一失的方式解释一下我在这里错过了什么吗?
更新
正如评论部分提到的 - 代码协定是一个不推荐使用的概念。这对我来说没关系,我只是想理解这个想法 - 在这种情况下,为什么我们可以使后置条件和对象不变量更严格?这与我的常识相矛盾,这意味着以前允许返回某些东西(或为对象不变量而发生),现在我们声明不再允许某些东西,这本书的作者告诉这种情况不会破坏向后兼容性。
答:
文中说,这些条件是“和”在一起的。这意味着您根本无法删除后置条件和不变量。无论您如何编写代码,都只能添加它们。
后置条件和不变量是退出时必须确保的东西。能够增加义务是有道理的。如果您要添加矛盾,则 CC 应将其标记为后置条件冲突。
从兼容性和扩展性的角度来看,基类的用户将获得他们期望的保证。他们可能会收到他们不知道或不关心的额外保证。
下一个:如何验证方法外部的条件
评论