I just tried to use Code Contracts, and I see no real advantages over an if statement.
Consider the following.
private static void BindClassesToInterfacesByConvention(string classesEndingWith
, string interfacesEndingwith) {
Contract.Requires<ArgumentNullexception>(
string.IsNullOrWhiteSpace(classesEndingWith)
, "classesEndingWith");
Contract.Requires<ArgumentNullException>(
string.IsNullOrWhitespace(interfacesEndingWith)
, "interfacesendingWith");
...
}
I find it way more confusing than simply using an if statement
private static void BindClassesToInterfacesByConvention(string classesEndingWith
, string interfacesEndingwith) {
if (string.IsNullOrWhiteSpace(classesEndingWith))
throw new ArgumentNullException("classesEndingWith");
if (string.IsNullOrWhitespace(interfacesEndingWith))
throw new ArgumentNullException("interfacesendingWith");
...
}
Code Contracts are supposed to warn me at compile time that a a contract is violated. So, I was expecting to get an error or a warning when I have written the following.
BindClassesToInterfacesByConvention(null, null);
And nothing happened, everything compiled just fine, and neither an error nor a warning message appeared.
In this scenario, I believe it is best to continue with the it statement. Or perhaps was it an unfair use of Code Contracts?
Code Contracts are a great idea let down by tooling that isn't quite there.
Firstly, in order to make the exceptions actually throw, you have to install the right extensions in Visual Studio and/or configure the correct settings on your project. Great fun if you have unit tests relying on the code contracts throwing exceptions at runtime and run them on a build server.
However, it is important to understand that the real purpose of Code Contracts isn't just to throw exceptions. It enables static code analysis (if you switch it on), which when enabled may be able to give you an error at compile time - but it does require you to do a lot of work to apply it pretty much everywhere in order for the static code analysis to really work. I believe that is the scenario you are trying to test? In which case I suggest you look at the code contracts setting for your project to make sure you have enabled all the static code checking (it will make your build rather long).
Furthermore and importantly, the code contracts allows you to communicate intent to the callers of your methods; Intellisense will pick up on the conditions you have specified (provided you install the correct extensions). The informatation about the code contracts can also automatically be added to the XML file that can accompany assemblies, which will then enable 3rd party users of your assembly to know about your requirements when they write their code, as well as allowing you to include this information in helpfiles built with Sandcastle etc.
It's a great idea, just not really fully implemented in the tools yet so you get some funny behavior once in a while. Personally I have pretty much stopped using them for the time being.
You are specifying a method that requires its arguments to be null or whitespace, then passing null. The contract is satisfied. That's why you got no contract violation. (Requires() requires throws the exception when the condition evaluates to false, not to true.)
Furthermore, even if you correct the contract, you shouldn't be throwing ArgumentNullException if the parameter value is a non-null string containing no characters or only whitespace characters. In that case you should throw an ArgumentException.
I would do this:
private static void BindClassesToInterfacesByConvention(string classesEndingWith
, string interfacesEndingwith) {
Contract.Requires<ArgumentNullException>(classesEndingWith != null
, "classesEndingWith");
Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(classesEndingWith)
, "classesEndingWith");
Contract.Requires<ArgumentNullException>(interfacesEndingWith != null
, "interfacesEndingWith");
Contract.Requires<ArgumentException>(!string.IsNullOrWhiteSpace(interfacesEndingWith)
, "interfacesEndingWith");
...
}
To download the Code Contracts analysis tools, including Visual Studio integration, visit http://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970
This is a subjective answer, but I would say the real statement here is: "I just tried to use Code Contracts, and I see no real advantages over a Unit Test"
For Example:
private void Foo(string something)
{
Contract.Requires<ArgumentNullException>(something != null, "something");
}
is equivalent as (NUnit testing):
void Foo(string something)
{
if (something == null)
throw new ArgumentNullException();
}
[Test]
[ExpectedException( typeof( ArgumentNullException ) )]
void foo_throws_exception_with_null_param()
{
Foo(null);
}
Which is better? Well from my (limited) experience the static analysis addon for VS is quite slow. If you have done a call to foo with an explicit null'ed variable then it'll pick it up. But it won't pick up nulls loaded dynamically and send to foo during user iteraction.
On the other hand, if you have an if-statement and a unit test to ensure it WILL throw an ArgumentNullException then you know that the exception is going to be thrown; and you can deal with it in the run-time environment... you can test anything that uses Foo to make sure it handles the exception.
Ensuring that explicit check is very fast with NUnit. The downside of unit testing is setting up the tests to begin with. So my opinion is that over time you'll save more time by being explicit, making unit tests and ensuring your application can handle if those exceptions are thrown... it'll just cost you more to begin with to set it up.
Yes, Code Contracts will warn you at compile time that a a contract is violated if you enable the static checking.It proved the Code Contract add-ons(Code Contracts for .NET)only works on Visual Studio 2013 or lower versions, but not Visual Studio 2015 or 2017.
On Visual Studio 2013:
On Visual Studio 2015, we can see the error information from Output window, but not in Error List window. This bug was already logged and fixed, but it can still be repro.Warnings and messages from static contract checking don't appear in the VS2015 error list
Latest update:
Install the latest Contracts.devlab9ts.msi(Currently, it's just RC version) will resolve the issue in Visual Studio 2015.
DotNet CodeContracts v.1.10.20606.1-rc2
Related
I'm about to embark on a new C# project. I was wondering what the difference is between using Code Contracts or Code Analyzers (in Roslyn). Am I misunderstanding the usage of each? Being a new project, I would like to maintain the integrity of the code. So I want other developers to adhere to specific code guidelines. I'll research each further, but I was wanting to get the opinion of the community first. Excuse the question, I'm still rather new to C# development.
They are two different tools.
Code Contracts is a way to declare and check... well, contracts, such as pre-conditions and post-conditions:
public class Foo
{
public Foo(object arg)
{
Contract.Requires<ArgumentNullException>(arg != null);
}
public object GetBar()
{
Contract.Ensures(Contract.Result<object>() != null);
// TODO:
}
}
CC check their conditions at run-time. This requires your assembly (not source code!) to be rewritten after compilation to inject appropriate calls into your code.
Code Analyzers use Roslyn to analyze source code while you're writing it.
They can help you to format code, to remind you to call Dispose on IDisposable, and so on, but they don't affect run-time behavior directly.
There are a number of analyzers, grouped by purpose into projects (like StyleCopAnalyzers), while Code Contracts is a standalone project.
(CC also have static analyzer, but I can't tell much here - it kills performance when used on real projects, so, for me it is usually turned off. Anyway, it is intended to check contracts.)
Code analyzers will analyze your code for common mistakes. They look at the structure of the code and the flow of data across to detect problems.
Another type of analyzers looks at the style (StyleCop for example), capitals, camel casing, prefixes, postfixes and what have you.
The third type are the code contracts you've mentioned, and this works slightly different. You declare the expected behavior of your code, for example what is expected of parameters passed into a method, which exceptions your code can throw etc. The contracts analyzer will then check whether calling code is passing in the right parameters (e.g. the analyzer will detect you passing in null and will raise an error if that's not allowed). At the same time it will check the "internal consistency" of your methods to ensure that you don't throw exceptions you're not allowed to throw. Depending on the implementation contracts can be validated at runtime or at compile time.
I have created C# unit tests (using VS test tools). Among others, there are tests checking exceptions like that:
Assert.AreEqual("Object reference not set to an instance of an object.", e.Message);
When I open my unit test file and click "Run tests" in the context menu, everything works fine. When I use the test explorer of Visual Studio and click "Run tests" there, I get exceptions saying that the message of the exception is different. Actually, it is the same as the one I am checking for but in another language. The tests running in both cases are the same, there are no language changes or anything else, just simple logic tests. My OS is in English, Visual Studio as well. I have similar tests in another solution and there everything works fine. This solution and one of the projects that I am writing unit tests for were created by a colleague which has the system in this foreign language. However, I can't find settings like that anywhere. Does someone have an idea where these could be? How do I get the tests running always in English?
Try using HResult instead.
Assert.AreEqual(val, e.HResult)
Shouldn't change depending on language.
HResult is a coded numerical value assigned to a specific exception, so using HResult you know which exception is being thrown.
Edit:
Or if you know what exception you are expecting, you could write your own Exception-"expecter".
protected static void ThrowsException<T>(Action action) where T : Exception
{
var thrown = false;
try
{
action();
}
catch (T)
{
thrown = true;
}
Assert.IsTrue(thrown);
}
And then use it like this:
ThrowsException<IndexOutOfRangeException>(() => MyController.MyAction());
Here is my solution for the tests, in case someone else need it. It is not really good when the tests are language dependent, so I now check for the exception type:
Assert.IsInstanceOfType(e, typeof(ArgumentNullException));
However, I would still like to know where the language is taken from. When I have everything in English, I really expect it to be in English.
Why don't you just use Throws with specific exception? Checking for a string message is really bad. In my opinion it's even cleaner than using IsInstanceOfType
var testDelegate = () => MyService.Method(params);
Assert.Throws<NullException>(testDelegate);
When not using ccrewrite (say the project is built by another developer without CC installed),
Is Contract.Requires<T>(cond) silently stripped or does it still result in behavior equivalent to if (!cond) { throw new T() }? (I don't care if it's another method call or two - but it should "always be checked".)
I ask because Contract.Requires<T> appears to behave differently than Contract.Requires, but I'm not sure "how" or "when".
The goal is to replace the construct on public contracts
if (x != null) throw new ArgumentNullException();
with a CC-compatible version that will still throw an exception when not performing a CC rewrite during the build step.
While the above with EndContractBlock does work with "Custom Parameter Validation" (ie. legacy contract mode) I would like to use "Standard Contract Requires" in the project.
I believe there may be an equivalency, because in "Custom Parameter Validation" mode I am not able to use Requires<T>; if there is no equivalency to an always-required-check, insight as to why would be nice.
I am fine losing Requires, Ensures, and leaving in the non-honored invariant contract methods and interface contracts when CC rewriting is not done as I value them for the static analysis - but I need these always-there boundary checks to argue for keeping CC.
Please see the Code Contracts manual. It definitely tells you all you need to know about how the various forms of Code Contract checking works and what options are required to be set when using each form.
What's the Difference Between Contract.Requires(bool cond) and Contract.Requires<TException>(bool cond)?
To answer your first question, see section 2.1 Preconditions in the manual. Briefly, here is the difference:
Contract.Requires(bool cond)
This will throw a private Contract.ContractException exception if the condition evaluates to false. You cannot catch this exception (since it's private from your point of view)—this is to discourage catching and handling it, thereby making the contracts pretty much worthless.
Contract.Requires<TException>(bool cond)
If the condition evaluates to false, the specified TException will be thrown. You cannot use this form without running the contract tools on all builds.
About ccrewrite
Specifically, on page 20, in section 5. Usage Guidelines, it tells you all the different forms of contracts that Code Contracts can work with, how they work, and what the build requirements for each are.
I'll briefly summarize, but please, download the manual and read it. It's quite good, though not in any way complete—you have to do a lot of experimentation to learn how to effectively use Code Contracts. Also, if you have access to PluralSight, John Sonmez has a course called Code Contracts which is a great introductory course; and Michael Perry has an awesome course called Provable Code.
Contract Checking Is Not Required for Released Code
If you don't need contract checking in released code, then:
Use Contract.Requires everywhere
Enable Runtime Checking on Debug builds only.
Code Contract Checking is Required for Released Code
If you require contract checking on released code, you have two options:
Use Code Contracts "native" pre-conditions:
Use Contract.Requires<TException> on public API methods (e.g. methods that will be called by users of your library) for which you want to throw specific exceptions, e.g. ArgumentException.
Use Contract.Requires For non-public API methods or public API methods for which you don't want to throw a specific exception.
Enable Runtime Checking on all builds.
Ensure you enable options to only emit pre-conditions and only on public surface area of your assembly—e.g. only those methods that are callable by your library consumers.
Use "legacy" contract checking:
This is your old school style if (cond) { throw new Exception(...) } guard blocks on your public API methods
Use manual inheritance to enforce contracts on derived types. (When using option 1, Code Contracts can perform automatic inheritance of contracts from base classes, helping you avoid Liskov Substitution Principle violations.)
Make sure to place the line Contracts.EndContractBlock() after all your if (cond) { throw new Exception(...) } blocks so that Code Contracts knows these are your contracts.
On non-public API methods, you can feel free to use Contract.Requires for your contracts.
Enable Runtime Checking only on Debug builds.
One thing to note about the above: Contract checking is always enabled on Debug builds. If other developers on your team will be building this library, they will also need to have Code Contracts installed.
From Section 5.1.3: Forcing Projects to build with Contracts:
If you are using scenario 2 (Requires〈Exn〉) and you make your source code available to other developers, you might want to alert them that they need to use the tools to build your source. If so, you can insert the following snippet into your project file at the end (after the import of CSharp or VisualBasic targets):
<PropertyGroup>
<CompileDependsOn>$(CompileDependsOn);CheckForCodeContracts</CompileDependsOn>
</PropertyGroup>
<Target Name="CheckForCodeContracts"
Condition="'$(CodeContractsImported)' != 'true'">
<Error Text="Project requires Code Contracts: http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx" />
</Target>
Also, see Section 6.1: Assembly Mode where it tells you the difference between Custom Parameter Validation and Standard Contract Requires. This section makes it quite clear that the contract rewriter (ccrewrite) is always run on Debug builds.
I recently discovered the .NET Contracts API, and, although I don't like the way of implementation using methods and not an extended syntax (Sing# did it right, in my opinion), I prefer using them over the old / regular way using if's for e.g. null-checking.
I'm also approaching my first Contract.Ensures-calls and I stumbled over the question how we would deal with Exceptions in a method containing a Contract.Ensures that suffered from an exception while running?
The word Contract.Ensures kinda feels like I have to handle the exceptions inside the method and get my class into correct state again, but what if I couldn't?
Let's say we have this class here:
public class PluginManager
{
private ILoadedFromAtCompileTimeUnknownAssembly extension;
public bool IsFinished { get; private set; }
public void Finish()
{
extension.Finish();
this.IsFinished = true;
}
}
can we use Contract.Ensures to ensure IsFinished is true after the method completed?
Yes. Ensures basically means "Ensures if the method terminates normally", i.e. without exceptions.
I find it very hard to get the concept of code contracts right. Code Contracts are meant to find programming errors. If applied that way you can remove the contracts of your release build and your application will continue to work perfectly.
BUT it is very hard to distinguish programming (aka logic errors) from configuration and input data issues. These checks must remain in your release builds. It is therefore a bad idea to use Code Contracts to check if an extension/plugin did correctly load because it is usually configured into your application. If you remove the contracts in your release build you get differerent behaviour of your application depending if you configure your app wrong in debug or release builds.
Contract violations are reported with only one exception type which makes it impossible to react in upper layers of your application to e.g. a configuration issue or a logic bug in your application. With react I do not mean to continue but to present a remotely useful message to the user/developer what went wrong.
Code Contract do look nice at the surface but I fear that most people use it in the wrong way. It is not meant to replace all of your null checks for input validation in your methods. You should replace only from the methods the null checks with code contracts where your are sure that a logic problem an not the input data is the root cause.
If you expect a file name in your e.g. console application as input and the the user did forget to supply the file name at the command line it is not a good idea to the greet the user with a ContracException.
The error message would be confusing to the user.
You cannot differentate programming errors from user input validation issues.
You cannot catch any specific ContractException because the exception type is internal.
See user documentation.
7.6 ContractException The ContractException type is not a public type and is emitted as a nested private type into each assembly for which
runtime contract checking is enabled. It is thus not possible to write
catch handlers catching only ContractException . Contract exceptions
can thus only be handled as part of a general exception backstop. The
rationale for this design is that programs should not contain control
logic that depends on contract failures, just like programs should not
catch ArgumentNullException or similar validation exceptions.
Here is my problem. I am a very big fan of Design by contract, I am using this concept especially when developing libraries that can be used by other developers. I just found out a new way of doing this which is: Contract.Requires instead of Exception:
So instead of having:
public void SomeMethod(string name){
if(name==null) throw new NullArgumentException("Null values not supported");
}
I now have:
public void SomeMethod(string name){
Contract.Requires(name != null);
}
EDIT: I am working under VS2010 on debug mode.
Problem: Contract.Requires does not do anything, even when name is null!
The MSDN documentation says:
Specifies a precondition contract for the enclosing method or
property.
But nothing is specified in case the condition is not met!
I also noticed there are other Contract.Requires overloads that throw exception, display message... but then what is Contract.Requires(Boolean) for?
EDIT Answer below highlighted that a plug-in must be installed to have the full power of Contract API but then what about Mono users who want their code to behave the same on different platforms?
You should do the following:
Install the Code Contracts add-in as nfechner has noted
Go to the project properties, 'Code Contracts' folder
Check 'Perform Runtime Contract Checking'
Switch 'Assembly Mode' to 'Standard Contract Requires'
Substitute your Contract.Requires with Contract.Requires<SomeException> (the first one throws System.Diagnostics.ContractException while the second throws the exception you specified which is important for public methods)
That's the basic setup. For more accurate configuration, refer to the manual
If you use Mono, probably, Contract class is empty. I haven't done this, but chapter seven from the Contracts manual seems to explain how to provide your own implementation.
From the Contract class docs:
Important
You must install a Visual Studio add-in to enforce contracts. The Code
Contracts Premium Edition add-in lets you specify static and run-time
checking of code contracts on the project Properties page. If you do
not enable run-time checking, contracts such as the Contract.Ensures
method will not throw exceptions during run time if a contract is
violated. The Visual Studio add-in does not ship with Visual Studio
2010 or the Windows SDK.
With a message like this it is usually helpful to specify exactly what you have done.
For example, you do not mention in the original message if you have installed the VS Addon, nor that you have enabled it under your project properties, or that you are actually running in debug vs release mode, etc.
Re Contract.Requires vs Contract.Requires<Exception>
Contract.Requires is recommended.
According to the manual
If your code must throw a particular exception on failure of a
particular precondition, you can use the generic overloaded form
below. (Please read Section 5.1 before committing to this form in your
code. You cannot use Requires < Exn <Exn>> without running the contract tools
on all builds. If you do, you will get a runtime failure everytime.)