【问题标题】:Do invariant assertions fit into C# programming?不变断言适合 C# 编程吗?
【发布时间】:2011-06-02 21:50:27
【问题描述】:

coders at work 一书中,作者问“如何在代码中使用不变量”。请解释一下这个问题的含义。

我看到了类不变量on wiki,但该示例是用 Java 编写的,我对 Java 的熟练程度不足以将这个示例与 C# 联系起来。 .NET 4.0 引入了不变性、协变和逆变,并且很好地解释了here. 不变性是如此广泛。作者对该词的使用似乎与单元测试有关。对于读过这本书的人来说,作者是什么意思?我们是在谈论做出假设并在单元测试之后简单地测试有效性吗?

【问题讨论】:

    标签: c# java .net computer-science invariants


    【解决方案1】:

    在这种情况下,不变量是指适用于参数的条件,并且在函数/方法的整个生命周期内保持为真。

    来自wikipedia

    在计算机科学中,谓词被称为操作序列的不变量,前提是:如果谓词在序列开始之前为真,则在序列结束时为真。

    在 .NET 中,可以使用 Code Contracts 检查/强制执行不变量。

    【讨论】:

    • 我认为你不需要阅读这本书来理解我的问题,但作者提出问题的方式是“事实问题”或“你如何使用这些东西”作为如果每个人都这样做。我从来没有故意将不变量用于任何目的,而在 .NET 中,我们似乎需要一个现成的属性来考虑它们。那么,不变量的普遍使用是否已成为过去,还是仅限于汇编/C/C++?
    • @P.Brian.Mackey - 我也从未使用过它们,但是,那些来自 CS 背景的人似乎确实尝试使用它们以试图获得更好的“正确性”。我猜他假设每个人都知道不变量以及如何使用它们 - 考虑一下书中提到的人:)
    【解决方案2】:

    在此上下文中的含义与 C#4 中引入的泛型的 co 和 contra 方差无关,而是与您链接到的 wikipedia 文章具有相同的含义。在 C# 中,这可以是调试断言(即Debug.Assert(condition))以及代码契约库。例如,ContractInvariantMethodAttribute 可以应用于断言类不变量的类中的方法:

    [ContractInvariantMethod]
    protected void ClassInvariant()
    {
        Contract.Invariant(someCondition);
    }
    

    【讨论】:

      【解决方案3】:

      Wiki 中的那个例子是用 JML 实现不变量,这是一种非常具体的、奇异的、也许是经过深思熟虑的研究技术,但它根本不是主流。此外,它不仅在谈论不变量,而且只是谈论断言一个 mutator 做了预期的事情,当我想到不变量时,这不是我想到的。我没有读过 Coders at Work,但我怀疑 Coders at Work 中的任何人都使用过 JML。

      无论如何,我一直认为不变量是“提前崩溃”的好方法,并且当实际上程序状态处于不合理(计划外)状态时,您的代码不会尝试做合理的事情。

      C# 代码中不变量的一个很好的例子可能是永远不要将一个对象提供给 N-Hibernate 进行保存,除非该对象已经传递了它的不变量,其中应该有很多以防止无意义的数据进入数据库。让我们看看我是否能想到任何其他的例子......

      • 假设您有一个 User 类,它是 总是应该有一个主要的 电子邮件地址属性,然后是不变量 在保存之前检查可能是 确保电子邮件地址字段不为空。 否则,其他应用程序逻辑 沿着假设的道路 所有人的电子邮件地址都存在 用户在尝试时可能会搞砸 稍后向用户发送电子邮件。

      • 进一步假设一个用户对象 “有很多”电子邮件对象,并假设 这对一个人来说没有任何意义 电子邮件在没有拥有用户的情况下存在,然后 电子邮件类的不变量 可能是为了确保电子邮件的引用 它的用户总是不为空,否则 你有一个孤立的电子邮件对象 可能导致空指针异常 当您尝试提及电子邮件的所有者时。

      • 假设您正在编写一个 GUI, 应该呈现状态 在传统的 Amazon S3 对象 WPF 表单。形式上的不变量 可能是为了确保表格 正确绑定到其对象 在执行任何事件处理程序之前 在那个表格上。

      • 假设您正在编写 StackOverflow。 这里的一个不变量可能是确保用户的 声誉水平永远不会是负面的,即使 如果用户正在接受声誉惩罚。 负面声誉可能会破裂 那些将体验呈现为的漂亮图表 时间的函数(除非准备好这些图表 在 0 y 轴下方绘制线条,它们 很可能……)。

      至于何时检查不变量,您可以在任何改变数据状态的方法的末尾执行此操作。在防御性编程的最激进和最偏执的水平上,您可以在所有方法之前和之后检查不变量。

      【讨论】:

        【解决方案4】:

        不变这个词并不意味着在某些条件下某些东西不会改变。有许多不同种类的不变量。例如,在物理学中,光速在洛伦兹变换下是不变的,即如果您更改为参考系,它不会改变。在编程中也有很多种不变量。有些类不变量在对象的生命周期内不会改变,方法不变量在函数的生命周期内不会改变,...

        类不变量是在该类的实例中始终(至少在可公开观察的时间)为真的东西。

        这与协方差/逆变方差无关。 Co-/Contra-variance 描述了哪些类型可以替换为具有不同(通用)参数或返回类型的其他类型。虽然您可以将某些东西称为不变量,因为它不支持协方差/反方差,但这是一种与类或方法不变量完全不同的不变量。

        例如,某种集合可能具有以下不变量:

        • 数据!= null
        • 大小 >= 0
        • 容量 >= 0
        • 大小

        有了这个类:

        class MyCollection<T>
        {
          private T[] data;
          private int size;
        
          public MyCollection()
          {
            data=new T[4];
          }
        
          public int Size{get{return size;}}
          public int Capacity{get{return data.Length;}}
        
          [ContractInvariantMethod]
          protected void ClassInvariant()
          {
            Contract.Invariant(data != null);
            Contract.Invariant(Size >= 0);
            Contract.Invariant(Capacity >= 0);
            Contract.Invariant(Size < Capacity);
          }
        }
        

        几乎每个类都有一些不变量,但不是每个人都强制执行它们。 .net 4 添加了一种使用代码协定记录和断言它们的好方法。

        【讨论】:

        • 有趣的是,.NET 不变性与其他类型的不变性无关。我不同意,但也许这就是我错的地方。也许类型不变性与类不变性和单元测试使用无关,或者仅在基本层面上相关。如果我们将“不变性”简单地定义为“不变”。问题是“你如何测试不变的东西”。或者,是“如何测试一系列有效值”的问题?
        • @P.Brian 有很多类型的不变量。类型变化与类不变量完全无关。我添加了一个介绍性段落。
        • @P.Brian 要了解如何在 .net 4 中强制执行类不变量,请参阅“Lee”的答案。如果您这样做(并选择正确的编译器设置),您的代码将被重写,因此它会在任何公共方法的末尾测试不变量。
        • 谢谢,ClassInvariant() 实现真的帮助我想象你在说什么。
        • @P.Brian Mackey:您似乎被“invariance”和“invariants”之间的发音相似性误导了。它们的发音相似,足以让人混淆,但 CodeInChaos 是绝对正确的:它们彼此没有任何关系。
        猜你喜欢
        • 2010-12-02
        • 2018-05-19
        • 2010-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多