. NET's contract class library is part of declarative programming practice and can bring many benefits to everyday programming:
- To improve the readability of the code, the user sees require and ensure knows what input the method accepts and what output it produces.
- Reduce duplicate validation code
- With third-party tools, you can easily generate API documentation for static code analysis and unit testing, which can be found in the Code contract home page
The contract class itself has been integrated into the System.Diagnostics.Contracts namespace after. NET 4.0, but if you want to use the contract method to implement runtime validation, you also need to install a VS plugin separately. After the installation, go to the project properties to turn on run-time check:
In this way, each time the project is compiled, the Ccrewrite tool in the plugin compiles the contract method into a valid check code, respectively, into the body of the function. So even if you put the Contract.ensures check at the beginning of the function (which is also recommended), this part of the logic will still appear at the end of the function after compilation, checking that the function end condition is satisfied.
It is important to note that if you want to use the run-time validation feature in both debug and release builds, you will need to set the runtime check to open separately when the project is set to debug and release compile.
The basic use of contract includes requires and ensures,requires to check whether the initial conditions are met at the beginning of the method and is typically used for parameter validation. The ensures method is used to check that the execution results are as expected at the end of the method, such as to check that the property is set correctly at the end of the property set method.
When the check fails, Contractexception is thrown by default, and requires and ensuresonthrow of generics can be used to specify other types of exceptions.
Public Async void GetPage (string entrypageurl) { contract.requires<ArgumentException>( Uri.iswellformeduristring (Entrypageurl, Urikind.absolute)); ... }
Contract has a cool feature, that is, you can define some checks in the interface, requiring all implementations to satisfy these check bars, so that you do not have to define the same check logic in each implementation of the interface, very elegant, but also in line with declaration Programming's original intention.
The following is the sample code:
[Contractclass (typeof(ibookrepositorycontract))] Public InterfaceIbookrepository {stringBookTitle {Get;Set; } voidCreate (stringname, Stream blob); } [Contractclassfor (typeof(ibookrepository))] Sealed classIbookrepositorycontract:ibookrepository { Public stringBookTitle {Get { return NULL; } Set{contract.requires (!string. Isnullorwhitespace (value),"Book title must isn't be empty."); Contract.Requires (string. Isnullorwhitespace ( This. BookTitle),"Book title has already been set."); } } Public voidCreate (stringname, Stream blob) {Contract.Requires<InvalidOperationException> (!string. Isnullorwhitespace ( This. BookTitle),"Book title hasn ' t been set"); } }
This eliminates the need to define these checks for all ibookrepository implementation classes.
Resources:
Http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf
http://blog.csdn.net/atfield/article/details/4465227
Http://www.cnblogs.com/yangecnu/p/The-evolution-of-argument-validation-in-DotNet.html
Implementing run-time validation with. NET Code Contracts