37

I wonder, how to properly use Code Contracts in .NET Core, so far I tried to add CC to my project, compile and debug. I'm confused by message, which is appearing in each call which uses Contract.Requires, and information found by googling.

The message states:

An assembly must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.Requires<TException> and CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite ....

As I can see there are no CC options in the project properties and as I can see CC's Github repository is nearly dead. Is the are any way how to successfully use CC in .NET Core?

And if not, is there any simple way how to replace them? I use Contract.Requires and ContractClassAttribute. Replacing Contract.Requires is obvious, but ContractClassAttribute is blowing my mind :-)

Geert Bellekens
  • 12,788
  • 2
  • 23
  • 50
Jiří Zajíček
  • 380
  • 1
  • 3
  • 9
  • Possible duplicate of [Building with Code Contracts?](http://stackoverflow.com/questions/18793558/building-with-code-contracts) also http://stackoverflow.com/questions/1209166/why-is-ccrewrite-exe-not-doing-anything-from-the-command-line?noredirect=1&lq=1 – hatchet - done with SOverflow Mar 09 '17 at 22:35
  • 1
    Nope, the first one deals only with Contract.Requires which I already have implemented and the second one deals with similar problem with different version of .NET. Approach of .NET Core is obviously different, so no this is not duplicate :-( UI for CC in VisualStudio is completely missing for .NET Core projects. – Jiří Zajíček Mar 09 '17 at 22:55
  • While it is not supported, it would probably not be too difficult to implement it as a Roslyn code analyzer. – Cory Nelson Mar 09 '17 at 23:09
  • 6
    [You already found yourself that Code Contracts not supporting .NET Core is an open issue that at least so far never got picked up.](https://github.com/Microsoft/CodeContracts/issues/231) That user jirizaj is you, right? It's unfortunate, but I'm not sure what you're hoping for here. –  Mar 09 '17 at 23:09
  • @hvd yes, that's me. I didn't figure, I'm not sure, so I hoped that somebody found a solution. Maybe CONTRACTS_FULL symbol can be somehow turned off. Maybe somebody will have a clue how to bring ContractClassAttribute, which I'm missing the most. – Jiří Zajíček Mar 09 '17 at 23:31
  • I don't think there is an easy replacement. You could remove the attribute, change the buddy class into extension methods on the Interface that do the precondition checks, but then you have to add one line of code in the methods and properties of the implementing classes. Not ideal, but at least the precondition code exists in only one place. I think to get better than that, you leave the domain of "simple". I can post an example as an answer if my comment isn't clear, but it would be ripe for downvotes since it doesn't really answer your question. – hatchet - done with SOverflow Mar 09 '17 at 23:43
  • @JiříZajíček The message about `CONTRACTS_FULL` is misleading. `Contract.Requires` isn't conditional on that symbol, the error message shouldn't be mentioning it, but the error message is shared across all methods. `Contract.Requires` requires the rewriter, regardless of symbols, throwing an exception otherwise. `ContractClassAttribute` is conditional on the symbol but requires the rewriter if you actually want it to work. You could create your own rewriter that does something similar, but the result would no longer be Code Contracts. –  Mar 10 '17 at 06:14
  • Thanks guys, in that case, I think it's better to go without code contracts as the project is small and I need to finish it soon. @hatchet thanks the example is not necessary :-) – Jiří Zajíček Mar 10 '17 at 10:14

2 Answers2

8

The answer is: Code Contracts is no longer supported for .NET Core. It's available in the .NET Core 2.0, but it's no longer maintained.

See the official statement at the docs page:

Note

Code contracts aren't supported in .NET 5+ (including .NET Core versions). Consider using Nullable reference types instead.

Also on Github thread (Are Code Contracts going to be supported in .NET Core going forwards? #6361):

We have stopped investing in code contracts a while ago. We've added it to .NET Core 2.0 as part of our compatibility effort, but I wouldn't recommend new code using it.

FWIW, we've looked at many code bases that use them and it seems the overwhelming usage is about null handling. The replacement for this is under way with C# 8's nullable-reference types.

— Immo Landwerth, Program manager on the .NET team at Microsoft. https://twitter.com/terrajobst

Dariusz Woźniak
  • 9,640
  • 6
  • 60
  • 73
4

First of all, let's understand what CodeContracts are, according to microsoft docs:

Code contracts provide a way to specify preconditions, postconditions, and object invariants in your code. Preconditions are requirements that must be met when entering a method or property. Postconditions describe expectations at the time the method or property code exits. Object invariants describe the expected state for a class that is in a good state.

Meaning, to make things simple, CodeContracts help us simplify tests in our code.

How do we use code contracts?

Consider this example:

if ( x == null ) throw new ...  
Contract.EndContractBlock(); // All previous "if" checks are preconditions  

What does it mean by preconditions one of two cases?

When if-then-throw statements appear in this form, the tools recognize them as legacy requires statements. If no other contracts follow the if-then-throw sequence, end the code with the Contract.EndContractBlock method.


You can use it also in Postconditions:

What are Postconditions?

Postconditions are contracts for the state of a method when it terminates. The postcondition is checked just before exiting a method. The run-time behavior of failed postconditions is determined by the runtime analyzer.

Unlike preconditions, postconditions may reference members with less visibility. A client may not be able to understand or make use of some of the information expressed by a postcondition using private state, but this does not affect the client's ability to use the method correctly.

Meaning, to make things short, Postconditions help us test our methods.

an Example would be:

Contract.Ensures( this.F > 0 );

Please note special postcontions:

  • You can refer to method return values in postconditions by using the expression Contract.Result<T>(), where T is replaced by the return type of the method. When the compiler is unable to infer the type, you must explicitly provide it.
  • A prestate value in a postcondition refers to the value of an expression at the start of a method or property. It uses the expression Contract.OldValue<T>(e), where T is the type of e. You can omit the generic type argument whenever the compiler is able to infer its type. (For example, the C# compiler always infers the type because it takes an argument.) There are several restrictions on what can occur in e and the contexts in which an old expression may appear. An old expression cannot contain another old expression. Most importantly, an old expression must refer to a value that existed in the method's precondition state. In other words, it must be an expression that can be evaluated as long as the method's precondition is true.

Finally you have Invariants:

Object invariants are conditions that should be true for each instance of a class whenever that object is visible to a client. They express the conditions under which the object is considered to be correct.

Meaning, Invariants help test our class code and instances.

An example would be:

[ContractInvariantMethod]  
protected void ObjectInvariant ()   
{  
Contract.Invariant(this.y >= 0);  
Contract.Invariant(this.x > this.y);  
...  
}  

Full example for proper use of CodeContracts:

using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net.Http.Headers;
using System.Diagnostics.Contracts;

namespace System.Net.Http
{
    public class FormUrlEncodedContent : ByteArrayContent
    {
        public FormUrlEncodedContent(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
            : base(GetContentByteArray(nameValueCollection))
        {
            Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
        }

        private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
        {
            if (nameValueCollection == null)
            {
                throw new ArgumentNullException(nameof(nameValueCollection));
            }
            Contract.EndContractBlock();

            // Encode and concatenate data
            StringBuilder builder = new StringBuilder();
            foreach (KeyValuePair<string, string> pair in nameValueCollection)
            {
                if (builder.Length > 0)
                {
                    builder.Append('&');
                }

                builder.Append(Encode(pair.Key));
                builder.Append('=');
                builder.Append(Encode(pair.Value));
            }

            return HttpRuleParser.DefaultHttpEncoding.GetBytes(builder.ToString());
        }

        private static string Encode(string data)
        {
            if (String.IsNullOrEmpty(data))
            {
                return String.Empty;
            }
            // Escape spaces as '+'.
            return Uri.EscapeDataString(data).Replace("%20", "+");
        }

        internal override Stream TryCreateContentReadStream() =>
            GetType() == typeof(FormUrlEncodedContent) ? CreateMemoryStreamForByteArray() : // type check ensures we use possible derived type's CreateContentReadStreamAsync override
            null;
    }
}
Barr J
  • 10,636
  • 1
  • 28
  • 46
  • 12
    This is a good explanation of code contracts and their usage, but it doesn't answer the OP's question. @Kousic's answer is better. – Hintham Oct 17 '18 at 12:12
  • "Is the are any way how to successfully use CC in .NET Core?" According to this, I answered the question :) – Barr J Oct 17 '18 at 13:05
  • 1
    Yes you explained the way which it can be used in Core, thank you :-). I think this way is not worth having another reference in the project. The best part about CC is the ability to extend interfaces and limit the input going to the implementation. Having contract class with defined contracts helped to increase code readability (one internal class in the same file as the interface) and security (how many times you forget or a junior just ignores argument checks - i'm considering simple and obvious checks like null check). This allowed me to have the contracts in all implementations instantly. – Jiří Zajíček Oct 21 '18 at 18:57
  • 3
    I downvoted this answer because while this compiles in C# 8.0 (after removing the `internal` bits of `FormUrlEncodedContent`), the actual code-contract parts of the code have no effect on the build process (i.e. passing in `null` to `GetContentByteArray` does not cause a build-time error nor warning (when C# 8.0 nullable reference types are disabled)). – Dai Jul 11 '20 at 00:48
  • No, it describes how to use code contracts in Framework, not in Core, because they're no longer supported in Core. – digitig Jun 05 '23 at 21:20