What's the diference between these two statements ?
Contract.Requires(string.IsNullOrWhiteSpace(userName)); Contract.Assume(string.IsNullOrWhiteSpace(userName));
Code Contracts provide a language-agnostic way to express coding assumptions in . NET programs. The contracts take the form of preconditions, postconditions, and object invariants. Contracts act as checked documentation of your external and internal APIs.
NET 4.0. Code Contracts API includes classes for static and runtime checks of code and allows you to define preconditions, postconditions, and invariants within a method.
Imagine you have a method like this:
bool ContainsAnX(string s) { return s.Contains("X"); }
Now, this method will always fail if you pass null
to it, so you want to ensure this never happens. This is what Contract.Requires
is for. It sets a precondition for the method, which must be true in order for the method to run correctly. In this case we would have:
bool ContainsAnX(string s) { Contract.Requires(s != null); return s.Contains("X"); }
(Note: Requires
and Ensures
must always be at the start of a method, as they are information about the method as a whole. Assume
is used in the code itself, as it is information about that point in the code.)
Now, in your code that calls the method "ContainsAnX", you must ensure that the string is not null. Your method might look like this:
void DoSomething() { var example = "hello world"; if (ContainsAnX(example)) Console.WriteLine("The string contains an 'X'."); else Console.WriteLine("The string does not contain an 'X'."); }
This will work fine, and the static checker can prove that example
is not null.
However, you might be calling into external libraries, which don't have any information about the values they return (i.e. they don't use Code Contracts). Let's change the example:
void DoSomething() { var example = OtherLibrary.FetchString(); if (ContainsAnX(example)) Console.WriteLine("The string contains an 'X'."); else Console.WriteLine("The string does not contain an 'X'."); }
If the OtherLibrary
doesn't use Code Contracts, the static checker will complain that example
might be null.
Maybe their documentation for the library says that the method will never return null (or should never!). In this case, we know more than the static checker does, so we can tell it to Assume
that the variable will never be null:
void DoSomething() { var example = OtherLibrary.FetchString(); Contract.Assume(example != null); if (ContainsAnX(example)) Console.WriteLine("The string contains an 'X'."); else Console.WriteLine("The string does not contain an 'X'."); }
Now this will be okay with the static checker. If you have runtime contracts enabled, the Assume will also be checked at run time.
Another case where you might need Assume is when your preconditions are very complex and the static checker is having a hard time proving them. In this case you can give it a bit of a nudge to help it along :)
In terms of runtime behavior there won't be much difference between using Assume and Requires. However, results with the static checker will differ greatly. The meaning of each is different as well, in terms of who is responsible for the error in case of failure:
It only differs design-time/static-analysis-time
Contract.Assume: "Instructs code analysis tools to assume that the specified condition is true, even if it cannot be statically proven to always be true" And: At run time, using this method is equivalent to using the Assert(Boolean) method.
Contract.Requires will guarantee that the given predicate is true and static code analyzers might raise an error if they can't 'prove' that is not the case. On Contract.Assume the static analyzer will continue/issue a warning/whatever the tool will decide.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With