何时在构造函数上使用[Pure]?


19

我正在学习.NET中的代码协定,并且试图了解纯构造函数的概念。该代码合同文档状态:

合同中调用的所有方法都必须是纯函数。也就是说,它们不得更新任何先前存在的状态。允许使用纯方法修改进入纯方法后创建的对象。

并且PureAttribute文档指出:

指示类型或方法是纯类型,即,它不进行任何可见状态更改。

对于方法,我理解这些语句,但是构造函数呢?假设您有一个像这样的课程:

public class Foo
{
    public int Value { get; set; }

    public Foo(int value) {
        this.Value = value;
    }
}

显然,此构造函数确实会影响新Foo对象的状态,但是它没有其他副作用(例如,它不操纵任何参数或调用任何非纯方法)。这是候选人[Pure]吗?[Pure]在构造函数上放置属性的意义是什么?何时应该在自己的代码中执行此操作?

Answers:


14

您使用以下方法装饰方法[Pure]

  • 如果该方法没有副作用。例如,如果该方法访问数据库并对其进行修改,或者其结果取决于数据库,则它不是纯粹的。

  • 并且如果您希望在代码合同中使用它。例如,如果该方法是pure方法,但是您无意在代码契约中使用它,那么添加[Pure]将没有任何好处,也不会使您的代码更快。

就构造函数而言,看起来它们在.NET中被视为纯函数,不需要显式属性。我查看了.NET Framework源代码中的几个构造函数,例如DateTime,它们没有[Pure]属性。

我认为这样做是出于以下几个原因:

  • [Pure]仅仅为了能够在合同中使用类/结构而不得不编写具有属性的无参数构造函数可能太不切实际。

  • 有些,例如String,没有显式的构造函数。

  • 构造器甚至在外部代码合同中也得到特殊待遇;例如,您不应该在其中抛出异常

  • [Pure]只是为了简化您的生活而制定的约定,但是没有实际的静态检查来确保用此属性修饰的方法是纯净的。void DestroyDatabase()可能被修饰为纯净,并且代码合同不会发现任何错误。

    当前,代码合同中没有组件可检查声明为pure的方法是否确实为pure。因此,如果程序员用[Pure]装饰了方法,那就相信了。

    代码合同5:方法纯度

  • .NET Framework本身包含不纯的构造函数。例如,List<T>(IEnumerable<T> collection)如果循环遍历集合有副作用,则实际上是不纯的。

  • 合同喊叫要保持简单。我可以轻松地想象一个诸如的合同Contract.Requires(!string.IsNullOrEmpty(name)),因此有充分的理由声明静态string.IsNullOrEmpty纯。

    另一方面,如果您需要a StringBuilder来构建字符串,然后通过调用业务类的实例方法来检查某些内容,则可能是在滥用合同。这就是为什么StringBuilder.ToString即使它可能不是也未标记为纯(是吗?)的原因


合同检查器采用了许多关于系统类型的代码合同,包括“ 任何以“ System.Diagnostics.Contracts.Contract”,“ System.String”,“ System.IO.Path”或“ System”开头的全限定名称的方法。 。键入“ ”。不幸的是,我不确定在进行代码契约时,查看.NET类型是否有用。
pswg 2014年

3
纯度是所有被调用的代码也必须是纯净的,或者调用者不是“纯净的”。我发现很难相信默认情况下所有构造函数都被视为纯函数。
Frank Hileman

@FrankHileman:我也是。我现在没有C#编译器,但是编写一个没有构造函数且没有[Pure]属性的类并在合同中的其他地方使用它来获得确定的答案就足够了。
Arseni Mourzenko 2014年

1

在这种情况下,除非构造对象,否则无法使用该对象。因此,构造函数是纯净的。如果构造函数调用了其他代码或调用了委托,而其他代码修改了mutable属性,那么它将不是纯粹的。为了更安全,最好使属性不变。


因此,纯构造函数是一种纯方法,只要它满足其他纯条件,就可以更改当前类的状态?顺便说一句,该属性是可变的,因为我想强调此类本身并不是纯洁的。
pswg 2014年

@pswg:您创建了一个有趣的问题,Microsoft可能必须回答。假设构造函数调用了一个修改可变属性的方法;构造函数仍然是纯净的吗?我认为从技术上讲不是这样,即使该修改对外部观看者“不可见”。由于在您的原始示例中没有调用其他代码,因此我想到的任何定义都必须是纯代码。
Frank Hileman

@pswg:除了属性集也是方法调用之外。我想您应该在MSDN论坛上询问。
Frank Hileman

我想,如果纯度的中心思想是该方法是否进行了任何可观察到的更改,那么从这个意义上讲,无论该方法是否调用了非纯方法,只要任何调用者都无法观察到这些更改,它仍然是一种纯净的方法。
pswg

@pswg:这是抽象定义。但是,如果我正在为这些事情编写分析器,则可能还会考虑使用非纯方法调用来使调用者变为非纯方法。只是为了简化实施。然后的问题是,构造函数是常规方法调用,还是分析进行了多深?
Frank Hileman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.