If you use abstract classes in your code, you will know that being able to control how they are used with code contracts will result in more robust code. But how exactly can we use code contracts with abstract classes? Especially since abstract classes are supposed to contain no implementation? Well, it is definitely possible, and here is how we do it.
If you have not worked with abstract classes before, we advise you to first read Chapter 2, Classes and Generics, to familiarise yourself with how abstract classes are used and created.
using
statement to the top of your Recipes.cs
class file:using System.Diagnostics.Contracts;
Shape
that defines two methods called Length()
and Width()
which each take an integer value as a parameter. Remember that abstract classes contain no implementation:public abstract class Shape { public abstract void Length(int value); public abstract void Width(int value); }
ShapeContract
that inherits the Shape
abstract class. It is here that our code contracts will reside:public abstract class ShapeContract : Shape { }
Length()
and Width()
methods of the Shape
abstract class and ensure that they require a non-zero parameter:public abstract class ShapeContract : Shape { public override void Length(int value) { Contract.Requires(value > 0, "Length must be greater than zero"); } public override void Width(int value) { Contract.Requires(value > 0, "Width must be greater than zero"); } }
ShapeContract
contract class to the Shape
abstract class. We will do this via the use of attributes. Add the following attribute to the top of your Shape
abstract class:[ContractClass(typeof(ShapeContract))]
Shape
abstract class will look like this:[ContractClass(typeof(ShapeContract))] public abstract class Shape { public abstract void Length(int value); public abstract void Width(int value); }
Shape
abstract class to the ShapeContract
abstract class as a means of telling the compiler which class the contracts need to act upon. We will do this by adding the following attribute to the top of the ShapeContract
class:[ContractClassFor(typeof(Shape))]
ShapeContract
class will look like this:[ContractClassFor(typeof(Shape))] public abstract class ShapeContract : Shape { public override void Length(int value) { Contract.Requires(value > 0, "Length must be greater than zero"); } public override void Width(int value) { Contract.Requires(value > 0, "Width must be greater than zero"); } }
Shape
abstract class. Create a new class called Rectangle
and inherit the Shape
abstract class:public class Rectangle : Shape { }
Rectangle
class with a red squiggly line. This is because no implementation of the Shape
class exists yet. Hover your mouse cursor over the red squiggly line and look at the lightbulb pop-up suggestion provided by Visual Studio:Shape
abstract class. You will notice that the methods inserted for you still don't contain any implementation and will throw NotImplementedException
if you don't add any implementation to the Length()
and Width()
methods:Rectangle
class, create two properties for the Length()
and Width()
methods and set these properties equal to the value of the supplied parameter value:public class Rectangle : Shape { private int _length { get; set; } private int _width { get; set; } public override void Length(int value) { _length = value; } public override void Width(int value) { _width = value; } }
using
statement to the Program.cs
class to bring the Chapter8
class into scope:using Chapter8;
Rectangle
class and pass some values to the Length()
and Width()
methods of the Rectangle
class:try { Rectangle oRectangle = new Rectangle(); oRectangle.Length(0); oRectangle.Width(1); } catch (Exception ex) { WriteLine(ex.Message); } ReadLine();
As we have added a zero value to the Length()
method, the code contract on the abstract class has correctly thrown an exception. Being able to implement code contracts on abstract classes allows developers to create better code, especially when working in teams where you need to convey implementation limitations based on certain business rules.
18.119.104.95