I'm learning about code contracts in .NET, and I'm trying to understand the idea of pure constructors. The code contracts documentation states:

All methods that are called within a contract must be pure; that is, they must not update any preexisting state. A pure method is allowed to modify objects that have been created after entry into the pure method.

And the PureAttribute documentation states:

Indicates that a type or method is pure, that is, it does not make any visible state changes.

I understand these statements when it comes to methods, but what about constructors? Suppose you had a class like this:

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

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

This constructor obviously does affect the state of the new Foo object, but it has no other side effects (e.g. it doesn't manipulate any of the parameters or call any non-pure methods). Is this a candidate for [Pure] or not? What is the significance of placing a [Pure] attribute on a constructor, and when should I do this in my own code?


You decorate a method with [Pure]:

  • If the method doesn't have side effects. For example, if the method accesses a database and modifies it or its result depends on the database, it's not pure.

  • And if you expect to use it in code contracts. For example, if the method is pure, but you have no intention to use it in code contracts, adding [Pure] would have no benefit and won't make your code faster.

As far as it concerns constructors, it looks like they are assumed to be pure in .NET and don't need an explicit attribute. I looked at several constructors in .NET Framework source, such as DateTime, and they don't have [Pure] attribute.

I suppose this is done for several reasons:

  • It may be too impractical to have to write a parameterless constructor with [Pure] attribute just to be able to use the class/struct in a contract.

  • Some, such as String, don't have explicit constructors.

  • The constructors receive special treatment even outside code contracts; for example, you're not expected to throw exceptions inside them.

  • [Pure] is just a convention which is here to simplify your life, but there is no actual static checking to ensure that the method decorated with this attribute is pure. void DestroyDatabase() may be decorated as being pure, and code contracts won't notice anything wrong.

    Currently there is no component of Code Contracts which checks if methods declared pure are pure indeed. Thus if a programmer decorated a method with [Pure], it’s just believed.

    From Code Contracts #5: Method purity

  • .NET Framework itself contains constructors which are not pure. For example, List<T>(IEnumerable<T> collection) is actually impure if looping through the collection has side effects.

  • Contracts shout be kept simple. I can easily imagine a contract such as Contract.Requires(!string.IsNullOrEmpty(name)), so there are good reasons to declare the static string.IsNullOrEmpty pure.

    On the other hand, if you need a StringBuilder in order to build the string you'll check then for something by calling an instance method of your business class, you're probably misusing the contracts. That's also why StringBuilder.ToString is not marked as pure, even if it might be (is it?)

  • Many code contracts on system types are assumed by the contract checker, including "any method whose fully qualified name begins with "System.Diagnostics.Contracts.Contract", "System.String", "System.IO.Path", or "System.Type"". Unfortunately, I'm not sure if looking at the .NET types is too useful when it comes to code contracts. – p.s.w.g Jul 1 '14 at 16:59
  • 3
    Purity is one of those things where all called code also has to be pure, or the caller is not "pure". I find it difficult to believe all constructors are considered pure by default. – Frank Hileman Jul 1 '14 at 17:09
  • @FrankHileman: me too. I don't have a C# compiler right now, but it would be enough to write a class with a constructor and no [Pure] attribute, and use it somewhere else in a contract to have a definitive answer. – Arseni Mourzenko Jul 1 '14 at 17:14

The object cannot be used until it is constructed in this case. Therefore the constructor is pure. If the constructor called other code, or invoked a delegate, and the other code modified the mutable property, it would not be pure. To be safer, it is better to make the property immutable.

  • So a pure constructor is a pure method which is allowed to change the state of the current class, as long as it satisfies the other conditions of being pure? BTW, The property is mutable because I wanted to emphasize that this class itself is not pure. – p.s.w.g Jul 1 '14 at 16:36
  • @p.s.w.g: You created an interesting question which probably has to be answered by Microsoft. Suppose the constructor invoked a method that modified the mutable property; would the constructor still be pure? I think technically it would not be, even though the modification is "invisible" to external viewers. Since there is no other code invoked in your original example, it must be pure by any definition I can think of. – Frank Hileman Jul 1 '14 at 17:07
  • @p.s.w.g: Except that the property set is also a method call.. I think you should ask on the MSDN forums. – Frank Hileman Jul 1 '14 at 17:11
  • I guess if the central idea of purity is whether or not the method makes any observable changes, then in that sense, regardless of whether or not it calls non-pure methods, as long as the changes can't be observed by any caller, it would still be a pure method. – p.s.w.g Jul 1 '14 at 18:55
  • @p.s.w.g: That is the abstract definition. But if I was writing an analyzer for these things, probably an non-pure method call would also be considered to make the caller non-pure. Just for simplicity of implementation. Then the question is, is a constructor a normal method call, or how deep does the analysis go. – Frank Hileman Jul 2 '14 at 2:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.