Generics: Base Class Constraint

Generics represent the new type introduced in .NET Framework 2.0. By understanding generics, you gain the ability to create classes, interfaces, methods, and delegates that can manipulate any kind of data in type safe mode. For sure, you have noticed that many times you had to implement some logical functionality in your application but for different data types. By using generics, this issue is solved. It would be false to stipulate that C# didn't offer solutions to create generalized classes or methods before. This was possible by using "object" references, but it wasn't type safe at all and also performing boxing and un-boxing operations was often required. The purpose of "generics" is to solve all these deficiencies. Here is a short example of a generic class:

public class MyGeneric<T>
{
   T obj;

   public MyGeneric(T o)
   {
      obj = o;
   }

   public void ShowGenericType()
   {
      Console.WriteLine("Type of T is: " + typeof(T));
   }
}

This is a very simple piece of code that doesn't require too much explanation. You can observe that the "MyGeneric" class has a parameter, T, that in the next example will be replaced by a real type. "T" isn't anything other than a placeholder for the real type. The same thing goes for the constructor that initializes the private object. There is a public method, "ShowGenericType", that does nothing more than show the real type of the generic class. Here is an example of how the generic class could be used:

class UsageOfGeneric
{
   public static void Main()
   {
      MyGeneric<int> objInt = new MyGeneric<int>(12);
      objInt.ShowGenericType();

      MyGeneric<string> objString =
         new MyGeneric<string>("I'm generic");
      objString.ShowGenericType();
   }
}

In the preceding code, you can see that you have created two generic objects of different types. The first is an object of type integer (MyGeneric<int> objInt = new MyGeneric<int>(12);), to which constructor you have passed an integer value; the second one is an object of type string (MyGeneric<string> objString = new MyGeneric<string>("I'm generic");), to which constructor you have passed a string value. The result of the ShowGenericType() method is clear that, for the object of type integer, the output is System.Int32; for the object of type string, the output is System.String. Event in the previous example, I had used only one generic parameter "T", you are not limited to that. You can use as many generic parameters for your class as you want. You just have to place a comma between them (MyGeneric<T,V>). One major observation is that a reference of one version of a generic type is not compatible with a different version of the same generic type (objInt != objString).

In the previous cases, type T could be anything because you didn't care. But, sometime you might want to impose a restriction for the generic types. The reason is quite straightforward; just think that in the generic class "MyGeneric" you have a method that needs to invoke a specific member from type T. To solve this issue, you have to take into consideration the fact that generics support constraints. There are five types of constraints supported by generics:

  1. Base class constraint: You can require a certain base class to be present in the type argument.
  2. Interface constraint: You can require one or multiple interfaces to be implemented by the type argument.
  3. Constructor constraint: You can require the type argument to supply a constructor without parameters; for example, new().
  4. Reference type constraint: You can require that the type argument be a reference type.
  5. Value type constraint: You can require that the type argument to be a value type; for example, struct.

Base Class Constraint

Base class constraint allows you to specify a base class from which the type argument must inherit. The main reasons for this type of constraint are: first, it allows you to use members of the based class; second, the base class constraint ensures that only arguments of base class type can be used in the generic class. For the second reason you have two options: the argument type can be either the base class itself or it can be any class derived from the specified base class. Here is an example of a base class constraint:

public class B : A
{

}

public class C
{

}

public class MyGeneric<T> where T : A
{
   private T objA;

   public MyGeneric(T obj)
   {
      objA = obj;
   }

   public void MyHello()
   {
      objA.HelloWorld();
   }
}

class UsageOfGenerics()
{
   public static void Main()
   {
      A a = new A();
      B b = new B();
      C c = new C();

      // Correct line of code.
      // Class A is the base class.
      MyGeneric<A> t1 = new MyGeneric(a);

      // Correct line of code.
      // Class B inherits from base class A.
      MyGeneric<B> t2 = new MyGeneric(b);

      // Incorrect line of code.
      // Class C doesn't inherit from base class A.
      MyGeneric<C> t3 = new MyGeneric(c);
   }
}

So, again the main reasons why base class constraint should be used are these: It enables the generic class to access members of the base class, and it ensures that only arguments types of base class type are valid obtaining a type safe environment.



About the Author

Michael Heliso

I work as a software developer for about 3 years. Until these days I have worked for different international software companies using different technologies and programming languages like: C/C++, lotus script, lotus API, C#, ASP.NET, MS-SQL, Oracle, Domino Server. My main interest, at this time, is focused on .NET technology (http://dotnetcaffe.net).

Comments

  • Nice article

    Posted by naksha on 07/11/2012 06:51am

    Thanks for sharing this article, can you share any other articles regarding other constraint in Genrics

    Reply
  • Nice article

    Posted by amitha on 07/11/2012 06:50am

    This is a nice article, can you share any article regarding other generic constraints

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds