Click here to Skip to main content
12,078,489 members (47,556 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

4.9K views
5 bookmarked
Posted

Use Generics Constraints to Reuse Code and Do Compile Time type checking

, 29 Jul 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
An example of how to use generics with constraints to reuse code and have compile time type validation.

Introduction

Assume you have a class with a functionality you wish to implement for a certain group of types.

Assume you also have a derived class which exposes that functionality too, but this derived class works with only a subset of those types.

So the trivial ways to achieve this are:

  1. Make the method input parameter type to be object and validate the type belongs to the allowed types before applying the functionality on it.
  2. Make the method input parameter to be a common interface, that way we ensure the type correctness in the base class, on the derived class we need to override the method and verify the type belongs to the subset of types before applying the functionality on it.
  3. Make the method a generic method, which will also require type validation code on both base and derived classes.

The way I suggest is using generics with constraints, the advantages of this approach is zero type validation code in both base and derived classes and that type validation is done at compile time for both classes.

Here is link to the documentation on generics constraints: http://msdn.microsoft.com/en-us/library/bb384067.aspx

Using the Code

Let's assume you are coding car warehouses with the following rule set:

Car warehouses can be general, European, German and Japanese.

General car warehouses can store all kind of cars, European warehouses can hold only European cars (including German) and so on.

Here is how I suggest to code this problem:

First let's define the car interfaces:

interface ICar {}

interface IEuropeanCar : ICar {}

interface IGermanCar : IEuropeanCar { }

interface IJapaneseCar : ICar {}

Now let's code the warehouse classes:

class GeneralCarWarehouse<T> where T : ICar
{
    private List<ICar> _carsInverntory = new List<ICar>();

    public void AddToInventory(T car)
    {
        _carsInverntory.Add(car);
    }
}

class EuropeanCarWarehouse<T> : GeneralCarWarehouse<T> where T : IEuropeanCar
{

}

class GermanCarWarehouse : EuropeanCarWarehouse<IGermanCar>
{

}

class JapaneseCarWarhouse : GeneralCarWarehouse<IJapaneseCar>
{

}

As you can see, the method AddToInventory is coded only once and does not perform any type validation in its code.

The GeneralCarWarehouse is a generic class and can be created with any type, but due to the constraint, only types inheriting from ICar can be used, trying to pass other types will not compile.

In order to define a general warehouse accepting all possible cars, we can create a class: MyWarehouse : GeneralCarWarehouse<ICar>.

The EuropeanCarWarehouse is also a generic type, but due to the constraint, it can accept only a subset of cars, those cars, which implement the IEuropeanCar. Once again, trying to create a concrete EuropeanCarWarehouse with a type that is not inheriting from the IEuropeanCar, will result in compile time error.

Finally, the GermanCarWarehouse can only accept cars implementing the IGermanCar.

Here is a usage example (which adds a few concrete classes):

class MyEuropeanCarWarehouse : EuropeanCarWarehouse<IEuropeanCar> { }

class BmwCar : IGermanCar { }

class FiatCar : IEuropeanCar { }

class ToyotaCar : IJapaneeseCar { }


class Program
{
    static void Main(string[] args)
    {
        var euroCarWareHouse = new MyEuropeanCarWarehouse();

        euroCarWareHouse.AddToInventory(new BmwCar());
        euroCarWareHouse.AddToInventory(new FiatCar());
        euroCarWareHouse.AddToInventory(new ToyotaCar());
   }
 }

If you will try to compile this code, you'll receive "a cannot convert error", since the ToyotaCar is not IEuropeanCar.

To summarize, the solution above solves the issue presented: Applying the same functionality to a group of types and its subgroups, without overriding the method code and with compile time type validation.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

No Biography provided

You may also be interested in...

Comments and Discussions

 
GeneralMy vote of 5 Pin
johannesnestler30-Jul-14 5:12
memberjohannesnestler30-Jul-14 5:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.160212.1 | Last Updated 29 Jul 2014
Article Copyright 2014 by Anton Kaminsky
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid