Code Contracts in C#
Posted by: Pravinkumar Dabade ,
on 8/27/2015,
in
Category C#
Abstract: Code Contracts API includes classes for static and runtime checks of code and allows you to define preconditions, postconditions, and invariants within a method. The Contracts class is found in the System.Diagnostics namespace.
Editorial Note: The Eiffel programming language introduced a concept called Design by contract where you can define preconditions, postconditions, and invariants on class methods. The basic idea was for a method to define a contract which states conditions that must be true when the method gets called. This is also called as preconditions. The method must also define conditions that must be true when it finishes execution. This is called as postconditions. The method can also define conditions that should remain true while the program is running. This is called as invariants.
.NET supports the Design by Contract idea via its Contracts class found in the System.Diagnostics namespace and introduced in .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. The preconditions specify the conditions the parameters must fulfill before a method can execute, postconditions that are verified upon completion of a method, and the invariants define the conditions that do not change during the execution of a method.
Why are Code Contracts needed?
Tracking issues of an application when your application is running, is one the foremost concerns of all the developers and administrators. Tracking can be performed in many ways. For example -
- You can apply tracing on our application and get the details of an application when the application is running
- You can use event logging mechanism when you are running the application. The messages can be seen using Event Viewer
- You can apply Performance Monitoring after a specific time interval and write live data from your application.
Code Contracts uses a different approach for tracking and managing issues within an application. Instead of validating everything that is returned from a method call, Code Contracts with the help of preconditions, postconditions, and invariants on methods, ensure that everything entering and leaving your methods are correct.
Note: Another way to define a contract is via the System.Diagnostics.Debug.Assert() . We will be using System.Diagnostics.Contracts in this article as there are a number of advantages over Debug.Assert. Some of these advantages include well named methods, contracts allowed on interfaces, nice integration with documentation tooling, ease of use and the community support for Code Contracts now that it is Open Source. One drawback of Code Contracts framework is that the compilation time increases as the assemblies are rewritten.
Code contracts are always defined at the starting of the method using a Contract class. Let's see some examples where we can use this class -
class Calculations
{
public int Division(int i, int j)
{
Contract.Requires(i > j,"i should be greater than j");
return i / j;
}
}
class Validation
{
public string GetCustomerPassword(string customerID)
{
Contract.Requires(!string.IsNullOrEmpty(customerID),"Customer ID cannot be Null");
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(customerID), "Exception!!");
Contract.Ensures(Contract.Result<string>() != null);
string password="AAA@1234";
if (customerID!=null)
{
return password;
}
else
{
return null;
}
}
}
In the above code, the first class is Calculations. In the calculations class, the method Division() checks whether divider is greater than the divisible number. If yes, then it will display a message.
In the second class - Validation, we are taking a CustomerID in a method GetCustomerPassword() as an input and then applying some checks like - if the customer ID is null or empty, display a message. It also throws an exception which is ArgumentNullException and checks if the result returned is not null.
For this we are using some methods from the Contract Class -
- Contract.Requires(Condition,userMessage) - This method is used to check the preconditions. It takes a condition argument and an optional argument called userMessage. If the condition fails, the message will get displayed.
- Contract.Requires<T>(Condition,userMessage) - In this method T is an exception class. If the customer ID is null, the exception is thrown. If you have configured Assert on contract, when it fails, it does not throw you an exception but the Trace.Assert() is performed to stop the execution.
- Contract.Result<T> - Use this method to get the return value of the function/property. The return value now can be used for evaluating the postconditions. For example, You can use the Contract.Result<T> to ensure a return value passes the post condition using Contract.Ensures().
- Contract.Ensures() - Use this method to evaluate the post conditions. For example, in our function we are using the Contract.Result<string> to ensure that it is not null.
- Contract.Invariants() - Use this method to apply the contracts on Method variables. These variable contracts checks the condition till the time method has not completed its execution.
Likewise, you can use different methods used by Contract class to evaluate preconditions and postconditions.
Defining Contracts on Interface
You can also define contracts on Interfaces. For example, IValidation is an interface which defines two properties like CustomerID and Password as shown below -
[ContractClass(typeof(ValidationContract))]
interface IValidation
{
string CustomerID{get;set;}
string Password{get;set;}
}
[ContractClassFor(typeof(IValidation))]
sealed class ValidationContract:IValidation
{
string IValidation.CustomerID
{
[Pure]
get
{
return Contract.Result<string>();
}
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(value), "Customer ID cannot be null!!");
}
}
string IValidation.Password
{
[Pure]
get
{
return Contract.Result<string>();
}
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(value), "Password cannot be null!!");
}
}
}
class Validation:IValidation
{
public string GetCustomerPassword(string customerID)
{
Contract.Requires(!string.IsNullOrEmpty(customerID),"Customer ID cannot be Null");
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(customerID), "Exception!!");
Contract.Ensures(Contract.Result<string>() != null);
string password="AAA@1234";
if (customerID!=null)
{
return password;
}
else
{
return null;
}
}
private string m_custID, m_PWD;
public string CustomerID
{
get
{
return m_custID;
}
set
{
m_custID = value;
}
}
public string Password
{
get
{
return m_PWD;
}
set
{
m_PWD = value;
}
}
}
In the above code, we have defined an interface called IValidation with an attribute [ContractClass]. This attribute takes an address of a class where we have implemented a contract for an Interface. The class ValidationContract makes use of properties defined in the interface and checks for the null values using Contract.Requires<T>. T is an exception class.
We have also marked the get accessor with an attribute [Pure]. The pure attribute ensures that the method or a property does not change the instance state of a class in which IValidation interface is implemented.
Editorial Note: .NET 4.5 introduces a new feature in Code Contracts called as abbreviations. Abbreviations are useful in scenarios where some contracts are required repeatedly. So if a method contains multiple contracts, just decorate that method with the ContractAbbreviator attribute, and this enables it to be used within other methods requiring this contract.
Code Contracts in .NET 4.5 and 4.6
Editorial Note: Although you can use the classes in the namespace System.Diagnostics.Contracts available with .NET 4.0, there is no Code Contract ‘tooling’ available in Visual Studio 2013 or in the latest versions of the .NET Framework (.NET 4.5 onwards). You may see the Contract class in .NET 4.5 and above, but the class does not function until you manually install the Code Contract library. The Code Contract library has now been released as an open source framework available on GitHub https://github.com/Microsoft/CodeContracts.
You need to download and run the Code Contracts .msi file found at https://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970 in order for Code Contracts to be available in Visual Studio 2013 and Visual Studio 2015. After the extensions are installed, a new tab appears in the properties of your solution called ‘Code Contracts’. You can specify the properties in this tab to configure Code Contracts in applications created using VS 2013 and VS 2015.
Note: Code contracts don’t work for the Visual Studio Express editions but do work with the Free Visual Studio 2013 Community Edition.
Conclusion
Code contracts introduced in .NET Framework 4.0 is a useful but underutilized feature. It enables a developer to publish various conditions that are necessary within an application. I hope this article has motivated you enough to use Code Contracts in your applications.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Pravinkumar, works as a freelance trainer and consultant on Microsoft Technologies. He is having over 10 years of experience in IT and is also a Microsoft Certified Trainer(MCT). He has conducted various corporate trainings on all versions of .NET Technologies including .NET, SharePoint Server, Microsoft SQL Server, Silverlight, ASP.NET, Microsoft PerformancePoint Server 2007 (Monitoring). He is passionate about learning new technologies from Microsoft. You can contact Pravinkumar at dabade[dot]pravinkumar [attherate] gmail[dot]com