Code contracts and inheritance

In my last posting about code contracts I introduced you how to force code contracts to classes through interfaces. In this posting I will go step further and I will show you how code contracts work in the case of inherited classes.

As a first thing let’s take a look at my interface and code contracts.

[ContractClass(typeof(ProductContracts))]
public interface IProduct
{
   
int Id { get; set
; }
   
string Name { get; set
; }
   
decimal Weight { get; set
; }
   
decimal Price { get; set
; }
}
 
[
ContractClassFor(typeof(IProduct))]
internal sealed class ProductContracts : IProduct
{
   
private
ProductContracts() { }
 
   
int IProduct
.Id
    {
       
get
        {
           
return default(int
);
        }
       
set
        {
           
Contract.Requires(value
> 0);
        }
    }
 
   
string IProduct
.Name
    {
       
get
        {
           
return default(string
);
        }
       
set
        {
           
Contract.Requires(!string.IsNullOrWhiteSpace(value
));
           
Contract.Requires(value
.Length <= 25);
        }
    }
 
   
decimal IProduct
.Weight
    {
       
get
        {
           
return default(decimal
);
        }
       
set
        {
           
Contract.Requires(value
> 3);
           
Contract.Requires(value
< 100);
        }
    }
 
   
decimal IProduct
.Price
    {
       
get
        {
           
return default(decimal
);
        }
       
set
        {
           
Contract.Requires(value
> 0);
           
Contract.Requires(value < 100);
        }
    }
}

And here is the product class that inherits IProduct interface.

public class Product : IProduct
{
   
public int Id { get; set
; }
   
public string Name { get; set
; }
   
public virtual decimal Weight { get; set
; }
   
public decimal Price { get; set; }
}

if we run this code and violate the code contract set to Id we will get ContractException.

public class Program
{
   
static void Main(string
[] args)
    {
       
var product = new Product();
        product.Id = -100;
    }
}

Now let’s make Product to be abstract class and let’s define new class called Food that adds one more contract to Weight property.

public class Food : Product
{
   
public override decimal
Weight
    {
       
get
        {
           
return base
.Weight;
        }
       
set
        {
           
Contract.Requires(value
> 1);
           
Contract.Requires(value
< 10);
 
           
base.Weight = value;
        }
    }
}

Now we should have the following rules at place for Food:

  1. weight must be greater than 1,
  2. weight must be greater than 3,
  3. weight must be less than 100,
  4. weight must be less than 10.

Interesting part is what happens when we try to violate the lower and upper limits of Food weight. To see what happens let’s try to violate rules #2 and #4. Just comment one of the last lines out in the following method to test another assignment.

public class Program
{
   
static void Main(string
[] args)
    {
       
var food = new Food();
        food.Weight = 12;
        food.Weight = 2;
    }
}

And here are the results as pictures to see where exceptions are thrown.

Violation of weight lower limit

Violation of weight upper limit

As you can see for both violations we get ContractException like expected.

Code contracts inheritance is powerful and at same time dangerous feature. Although you can always narrow down the conditions that come from more general classes it is possible to define impossible or conflicting contracts at different points in inheritance hierarchy.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    4 thoughts on “Code contracts and inheritance

    • May 12, 2010 at 4:27 pm
      Permalink

      Very nice! I’m curious, what’s the performance cost of a contract vs non-contract? I know you don’t get something for nothing, but I was curious just how “heavy” it is.

    • May 12, 2010 at 5:54 pm
      Permalink

      Thanks for question James!

      I plan to make some performance measuring during next couple of days. So, stay tuned :)

    • May 12, 2010 at 7:46 pm
      Permalink

      why would we use class code contracts vs data annotation attributes?

    • May 31, 2010 at 1:13 pm
      Permalink

      Isn´t it a violation of the Liskov substitution principle, when you are tightening the preconditions from w < 100 to w < 10? It seems to me like something the code contract framework should catch and disallow. I heard from Mike Barnett, that Code Contracts does not support the loosening of preconditions in derived classes, which seem even more weird if they allow them to be tightened.

    Leave a Reply

    Your email address will not be published. Required fields are marked *