Ioannis Vranos said:
Templates are instantiated at compile time while Generics at run-time.
Also Generics do not allow specialisations.
Let me expand on this a little. Generics are actually instantiated at
compile time, i.e. when the compilation from the intermediate language (IL)
to machine code happens. It may occur at runtime (JIT), or it can be
compiled ahead of time (pre-compiled with NGEN).
One major difference between generics and templates (in my opinion) is that
parameter types for generics are assumed to have methods only of Object type
(the base of all types) unless specified otherwise with "constraints".
Whereas parameter types for templates are assumed to have any methods
possible. This key difference makes it impossible to use generics for
generic meta-programming.
Ultimately (again IMHO) the above restriction for generics is the
consequence of its implementation. The major problem which was tried to be
avoided when generics were designed is code bloat. I'm judging by early
articles where the point of code bloat was emphasized frequently. So the
..NET designers decided to merge generic instantiations where parameter types
are derived from Object. Also the fact that all coding errors have to be
caught when the code is compiled into IL (versus when IL is compiled into
machine code), forces IL to be well defined/unambiguous. This makes
impossible for generic parameter types to have methods other than of Object
type, because Object is the least common denominator of all types in .NET.
So as I say avoiding code bloat seems to be one of the major reasons for
restricting "genericity" of generics. But there is a little irony here.
The "code bloat" argument was exploited so much by early articles on C# v2,
that it might seem C# does a better job in this respect then C++. But this
is not true. The sacrifice was for nothing! C++ does better job with code
bloat than C#. And here is how. In C# generic instantiations with
parameters of "value" types (types which are allocated on the stack) cannot
be merged. That is. List<int> and List<uint> will result in duplicating
the code of the generic class List<T> for type int and uint. But C++ is
smarter in this respect. Not only C++ linker merges template instantiations
for pointer type parameters (pointer is a rough equivalent of Object type in
C#), but it also merges _any_ methods with identical code. So in the above
example, code for List<int> and List<unsigned> template instantiations will
be merged if identical.
I won't laugh at C#/.NET guys for promoting generics over templates on the
merits of better handling the code bloat. Designing virtual machines is a
hard job. But the irony still stands.