C# Frequently Asked Questions

The C# team posts answers to common questions

How do C# generics compare to C++ templates?

Q: How do C# generics compare to C++ templates?

A: This is really a fairly complex topic.

Anders has touched on it in an interview.

I should state at the outset that the goals of generics are not the same as the goals of templates. There are some things that templates do better than generics, and vice versa.

Model

C++ templates use a compile-time model. When a template is used in a C++ program, the effect is as if a sophisticated macro processor had been used.

C# generics are not just a feature of the compiler, but also a feature of the runtime. A generic type such as List<T> maintains its generic-ness (genericity) after it has been compiled. Or, to look at it another way, the substitution that the C++ compiler does at compile time is done at JIT time in the C# generic world.

Error Checking

Error is best illustrated through an example. Consider a 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. 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 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.

It is possible to work around this at runtime using reflection, but the implementation isn't as clean and there may be a performance loss. We may address some of these issues in future releases

Run-time 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.

Space Use

The use of space is different between C++ and C#.  Because C++ templates are done at compile time, each use of a different type in a template results in a separate chunk of code being created by the compiler.

In the C# world, it's somewhat different. The actual implementations using a specific type are created at runtime. When the runtime creates a type like List<int>, the JIT will see if that has already been created. If it has, it merely users that code. If not, it will take the IL that the compiler generated and do appropriate replacements with the actual type.

That's not quite correct. There is a separate native code path for every value type, but since reference types are all reference-sized, they can share their implementation.

This means that the C# approach should have a smaller footprint on disk, and in memory, so that's an advantage for generics over C++ templates.

In fact, the C++ linker implements a feature known as “template folding“, where the linker looks for native code sections that are identical, and if it finds them, folds them together. So it's not a clear-cut as it would seem to be.

Template metaprogramming

C++ templates are sometimes used for a technique known as template metaprogramming. There is no way to do this in C#.

[Author: Eric Gunnerson]

Published Friday, March 12, 2004 8:58 PM by CSharpFAQ

Comments

 

Jerry Pisk said:

Why would you use generics if you limit your types to classes implementing a single interface? Why wouldn't you just use that interface directly? So instead of:

Class List<T> where T:IComparable
{
void Add(T Item) {...};
}

you'd use:


Class List
{
void Add(IComparable Item) {...};
}

The resulting effect is the same, it's faster, the code is easier to read and thanks to refactoring code it's not such a big deal to change your underlying interface.

The only reason to use generics is when valid types do not share a common base class (read other then Object).
March 13, 2004 1:05 AM
 

Ferris Beuller said:

JIT is COMPILE TIME u twonk, just a during the running of the program it decides to "compile" "just in time". You mean BUILD TIME surely, not compile time.
March 13, 2004 5:02 AM
 

Ferris Beuller said:

C++ Templates are PREPROCESSOR TIME, not compile time, the preprocesssor takes care or them not the compiler, no?

This is one thing I hate about Kludge++ (C++), is the mess of precompile substitution that you cant debug. The day you go there on the CLR is the day I dump the technology.
March 13, 2004 5:03 AM
 

Ferris Beuller said:

You can tell how bad Cludge++ (C++) is because of the fat that you need a template to hack in the abstraction of "properties" and these are only in the COM world "by design" for unmanaged code.
March 13, 2004 5:05 AM
 

Bryan's Blog Of Doom said:

March 13, 2004 12:51 PM
 

Bryan Batchelder said:

Hmmmm.
March 13, 2004 9:52 AM
 

Eric Gunnerson said:

Jerry,

I think there are two reasons generics work better than interfaces.

First, it's hard to know up front what kind of types you might want to use.

Second, interfaces require boxing for value types, and also introduce copy semantics where you don't want them.

Third, generic methods allow you to do things you couldn't do before.

Oh, and a bonus forth reason - if you go with the base class approach, you have to add casts to your code.
March 13, 2004 11:16 AM
 

Jerry Pisk said:

Eric, I was talking about generics with type constraints. I understand what generics are and can do and I use them (quite a lot) in my C++ code but I don't understand why the concept of type constraints was introduced, if you don't want to use generics but rather work with a single type you can just use interfaces.
March 13, 2004 6:40 PM
 

Daniel O'Connell said:

Thoughts on generics
March 14, 2004 8:42 AM
 

Eric Gunnerson said:

Jerry,

You can use interfaces instead, but ther are two disadvantages.

1) If you are ever using the underlying type rather than the interface, you'll have to cast from the interface back to the underlying type. Whether this is an issue depends on your use.

2) Value types that are converted to interfaces are boxed.
March 14, 2004 7:49 PM
 

Juan Wajnerman said:

I've just write a trick about operators and generics in my weblog. Maybe you want to read it and send your opinions.

March 15, 2004 7:25 PM
 

Rick Byers said:

There are a number of other generic programming techniques that you can do with C++ templates (and generics in other languages like Haskell), that you can't do with .NET or Java generics. See this paper for details:

http://www.osl.iu.edu/publications/pubs/2003/comparing_generic_programming03.pdf
March 17, 2004 11:21 AM
 

Daniel Jin said:

Jerry,

main point here is the type safety.

in your List example of adding with IComparable. I can basically cast anything that implements IComparable interface and try to add it to the list. during runtime, most likely when IComparable.CompareTo is called, some kind of checking will throw an exception if the two items I'm trying to compare are not of the same type (yet they both implement IComparable). that's no good.

with generics, I can catch this at compile time, verify that whatever list I create will only accept 1 type and 1 type only. and with ability to specify constraint, I can implement something like a generic sorted list or binary tree routine that is strongly typed when I program.
March 18, 2004 7:16 AM
 

Juan Wajnerman said:

March 20, 2004 1:34 AM
 

Anne Onymous said:

I think everyone here has made some good points about the “generics with constraints” versus “interfaces” debate and like most equivalent tools there’s a time to use one over the other.

It seems to me that you’d want to use “generics with constraints” when type safety is important (i.e. you want to make sure everything is the same type). However, sometimes this isn’t flexible enough (for example you want to be able to plug in different types at runtime) and that’s when you’d use interfaces.

Granted, I’m sure you could manipulate generics to do the latter, but I don’t clearly see how this could be done without some sort of reflection, and that would make the code confusing.
March 25, 2004 5:11 PM
 

Daniel Jin said:

one thing I didn't make clear in my previous comment is that constraints are useful to the implementation of things like generic sorted list or generic binary tree because it only makes sense to put something sortable into such data structures. and constraints (IComparable) are the way to guaranttee that you only get a strongly typed sorted list of a particular sortable (comparable) item. anything non-sortable (doesn't implement IComparable) cannot be used as the base type for a sorted list.
April 1, 2004 8:05 AM
 

Jiri Soukup said:

I am working on data structures imlemented as a library of associations which are automatically compatible with UML (C++,Java,C#). Because these involve cooperation of two or more classes, templates/generics are needed. The more work you move to preprocessor or compiler the safer is the code. Finding errors in the run time is bad news.
Templates tell me about incompatibility of the class in the comile time. Try to comment out B::prt() in this example:
template<class T> class A {
int a;
public: void foo(T *t){t->prt();}
};
class B {
public: void xyz(){};
public: void prt(){cout << "hello\n";}
};
int main(){
A<B> a; B b;
a.foo(&b);
April 27, 2004 5:01 PM
 

Dan Fernandez's Blog said:

June 21, 2004 10:04 PM
 

K. Scott Allen's Blog said:

July 10, 2004 9:41 PM
 

.NET Insights said:

January 7, 2005 4:44 AM
 

Dan Fernandez's Blog said:

January 7, 2005 12:32 PM
 

Intelligent Design said:

I came across an interesting quote from Tony Northrup regarding .net Generics: “I haven’t been able to

December 4, 2007 7:31 AM
 

Intelligent Design said:

I came across an interesting quote from Tony Northrup regarding .net Generics: “I haven’t been able to

December 4, 2007 7:33 AM
 

C Frequently Asked Questions How do C generics compare to C templates | Green Tea Fat Burner said:

June 7, 2009 10:02 PM
 

YOUR way of saving changes in the C# application... - Emuforums.com said:

June 9, 2009 1:32 AM
 

C Frequently Asked Questions How do C generics compare to C templates | Quick Diets said:

June 9, 2009 7:05 AM
Anonymous comments are disabled

© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker