The Pure attribute was added to .NET in version 4 as part of the Code Contracts initiative. Use of the PureAttribute Class indicates that a type or method is functionally "pure", i.e. it does not make any visible state changes. The idea was that Pure and other attributes/functions in the System.Diagnostics.Contracts namespace would be used to decorate classes and methods throughout .NET's Base Class Library (BCL).
Once that was done, the Code Contracts tooling could be used to perform advanced analysis and bug detection. However, the Code Contracts project failed. While there were several reasons for this, some of the more compelling ones include:
- The syntax was verbose, requiring full lines where developers would prefer to use attributes.
- The contracts were not exposed via reflection, eliminating the possibility for 3rd party tooling.
- The contracts were not exposed XML docs, meaning they could not be automatically included in documentation.
- When a contract was violated for any reason, the application crashed immediately with no chance for logging or corrective action.
- The tooling was outside the normal compilation path, requiring additional steps and making the use of build servers more difficult.
Since the end of the Code Contracts project, the Roslyn analyzers have taken over as the static analysis tool of choice. Roslyn analyzers are part of the normal VB/C# compiler pipeline, so their use doesn't add any complexity to the build process.
This leaves the question, "What to do with the code contract attributes?" Dan Moseley of Microsoft reports, "We don't use or enforce those and generally have been removing contract annotations."
Andrew Arnott, another Microsoft employee, counters with the idea that the Pure attribute specifically could still be of use:
But [Pure] is useful because one can write analyzers that will flag a warning when a [Pure] method is executed without doing anything with the result.
The basic idea behind this is any method marked as Pure should never have side effects. Its only purpose is to return a value. If it returns a value, and that value is subsequently ignored, then there was no reason to call the method in the first place. Therefore, the warning would always indicate a mistake.
And that's what should happen. If you are using Microsoft.CodeQuality.Analyzers, then rule CA1806 will warn you about ignoring the results of a Pure method. But there are two catches:
First, it cannot warn you if a method is improperly marked as Pure. That capability is theoretically possible, as Pure methods should only read from other pure methods.
Secondly, you must include the compiler constant "CONTRACTS_FULL". The Pure attribute itself is marked with a Conditional attribute. This means that without the aforementioned compiler constant, the Pure attribute will be stripped away from your compiled code. This actually happened to some methods in .NET's immutable collections library.
InfoQ asks: What other Code Contracts features would you like to see in modern .NET development?