C# generics vs C++ templates

Generics are not a completely new construct; similar concepts exist with other languages. For example, C++ templates can be compared to generics. However, there's a big difference between C++ templates and .NET generics.

Model

With C++ templates the source code of the template is required when a template is instantiated with a specific type. When a template is used in a C++ program, the effect is as if a sophisticated macro processor had been used, that is each use of a different type in a template results in a separate chunk of source code being created by the compiler.

Contrary to C++ templates, C# generics are not only a construct of the C# language; generics are defined with the Common Language Runtime(CLR). When a generic type is used in a C+ program, it maintains its generic-ness (genericity) after it has been compiled; the actual implementations using a specific type are created at runtime, that is to say that the substitution that the C++ compiler does at compile time is done at JIT time in the C# generic world. This makes it possible to instantiate generics with a specific type in Visual Basic even though the generic class was defined with C#.

Error Checking

Error is best illustrated through an example. Consider a C++ template that has a method like this;

T Add(T t1, Tt2) { return t1 + t2; }

the C++ compiler will be able to parse this method successfully. As mentioned above, when this template is actually used, the Ts will be replaced with an actual type. If a type such as int is used, the compiler will be able to create the Add method correctly, as it knows how to add two ints. If a type such as Employee was used, the compiler would issue an error, as the compiler would know that there was no way to add two Employees.

The C# generics world is very different. Because the type that is used with the generic is not known at compile time, the compiler needs additional information about the type that will be used with a generic class. This is done through constraints, which allow the author to constrain the types that can be used with a generic type. For example:

Class List<T> where T:IComparable

means that whenever I use a T in my implementation, I can call the CompareTo() function on it.

Constraints could theoretically provide nearly the same level of flexibility that templates do, but that would require a very complex constraint syntax. For the Whidbey release, only certain operations can be specified through contraints, which limits the number of operations you can perform.

For example, there is no way to say that a generic type must have an add operator, so you can't write “a + b“ in a generic class.

Runtime Operations

Generics in C# have full run-time support. If you use reflection, you will find that you can reflect over generic types, and create them at runtime. There's no real analog of this in the C++ world.