19

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?

2 Answers 2

16

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?)

4
  • 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
    Commented Jul 1, 2014 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. Commented Jul 1, 2014 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. Commented Jul 1, 2014 at 17:14
  • I find the assertion that any constructor is pure baffling. Maybe I'm missing something, but the entire purpose of a constructor is to create a side-effect. Even a parameterless constructor isn't pure if the class has a single field or property. I'm perfectly willing to be proven wrong here, but if to succeed, you'll have to completely upend my understanding of determinism in programming. Commented Apr 10, 2023 at 18:27
1

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.

7
  • 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
    Commented Jul 1, 2014 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. Commented Jul 1, 2014 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. Commented Jul 1, 2014 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
    Commented Jul 1, 2014 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. Commented Jul 2, 2014 at 2:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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