Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First off, you might want to read <a href="http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx" rel="noreferrer">my 2009 article on this subject</a>.</p> <p>The primary difference to my mind between C++ templates and C# generics is that C++ templates actually <em>completely recompile the code upon construction of the template</em>. The pros and cons of the C++ approach are many:</p> <ul> <li><p>PRO: You can effectively create constraints like "the type argument T must have an addition operator"; if the code contains a couple of Ts added to each other then the template will not compile if you construct it with a type argument that doesn't permit addition.</p></li> <li><p>CON: You can accidentally create undocumented constraints like "the type argument T must have an addition operator".</p></li> </ul> <p>In C# you have to <em>say</em> what the constraints are which helps the user, but you are limited to only a small set of possible constraints: interfaces, base classes, value vs reference type and default constructor constraints, and that's all.</p> <ul> <li><p>PRO: Semantic analysis can be completely different for two different constructions. If you want that, that's awesome.</p></li> <li><p>CON: Semantic analysis can be completely different for two different constructions. If you don't want that, that's a bug waiting to happen.</p></li> </ul> <p>In C# the semantic analysis is done <em>once</em> no matter how many times the type is constructed, and it is therefore required to work with <em>any</em> type argument that meets the constraints, not just the type arguments that are actually supplied.</p> <ul> <li><p>PRO: You only generate the code for exactly the constructions you need.</p></li> <li><p>CON: You generate the code for all the constructions you use. </p></li> </ul> <p>Templates can cause codegen to get large. In C#, the IL for a generic type is generated once, and then at runtime the jitter does codegen for all the types your program uses. This has a small performance cost, but it is mitigated somewhat by the fact that the jitter actually only generates code once for <em>all reference type arguments</em>. So if you have <code>List&lt;object&gt;</code> and <code>List&lt;string&gt;</code> then the jitted code is only generated once and used for both. <code>List&lt;int&gt;</code> and <code>List&lt;short&gt;</code> by contrast jits the code twice.</p> <ul> <li><p>PRO: when you use a template library, you have the source code right there.</p></li> <li><p>CON: to use a template library you have to have the source code. </p></li> </ul> <p>In C#, generic types are first-class types. If you stick them in a library, you can use that library anywhere without having to ship the source code.</p> <p>And finally:</p> <ul> <li><p>PRO: Templates permit template metaprogramming.</p></li> <li><p>CON: Template metaprogramming is hard to understand for novices.</p></li> <li><p>CON: The template system actually does not permit some type topologies that are extremely straightforward in a generic system.</p></li> </ul> <p>For example, I imagine that it would be difficult to do something like this in C++:</p> <pre><code>class D&lt;T&gt; { class S { } D&lt;D&lt;T&gt;.S&gt; ds; } </code></pre> <p>In C# generics, no problem. At runtime the type is only built <em>once</em> for all reference type arguments.</p> <p>But in C++ templates, what happens when you have <code>D&lt;int&gt;</code>? The interior type constructs a field of type <code>D&lt;D&lt;int&gt;.S&gt;</code>, so we need to construct that type. But that type constructs a field of type <code>D&lt;D&lt;D&lt;int&gt;.S&gt;.S&gt;</code>... and so on to infinity.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload