{"id":17093,"date":"2009-08-14T07:00:00","date_gmt":"2009-08-14T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/08\/14\/why-cant-i-declare-a-type-that-derives-from-a-generic-type-parameter\/"},"modified":"2009-08-14T07:00:00","modified_gmt":"2009-08-14T07:00:00","slug":"why-cant-i-declare-a-type-that-derives-from-a-generic-type-parameter","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090814-00\/?p=17093","title":{"rendered":"Why can&#039;t I declare a type that derives from a generic type parameter?"},"content":{"rendered":"<p>\nA lot of questions about C# generics come from the starting point\nthat they are just a cutesy C# name for C++ templates.\nBut while the two may look similar in the source code,\nthey are actually quite different.\n<\/p>\n<p>\nC++ templates are macros on steroids.\nNo code gets generated when a template is &#8220;compiled&#8221;;\nthe compiler merely hangs onto the source code,\nand when you finally instantiate it,\nthe actual type is inserted and code generation takes place.\n<\/p>\n<pre>\n\/\/ C++ template\ntemplate&lt;class T&gt;\nclass Abel\n{\npublic:\n int DoBloober(T t, int i) { return t.Bloober(i); }\n};\n<\/pre>\n<p>\nThis is a perfectly legal (if strange) C++ template class.\nBut when the compiler encounters this template,\nthere are a whole bunch of things left unknown.\nWhat is the return type of <code>T::Bloober<\/code>?\nCan it be converted to an <code>int<\/code>?\nIs <code>T::Bloober<\/code> a static method?\nAn instance method?\nA virtual instance method?\nA method on a virtual base class?\nWhat is the calling convention?\nDoes <code>T::Bloober<\/code> take an <code>int<\/code> argument?\nOr maybe it&#8217;s a <code>double<\/code>?\nEven stranger, it might accept a <code>Canoe<\/code> which\ngets converted from an <code>int<\/code> by a\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/05\/24\/605974.aspx\">\nconverting constructor<\/a>.\nOr maybe it&#8217;s a function that takes two parameters,\nbut the second parameter has a default value.\n<\/p>\n<p>\nNobody knows the answers to these questions, not even the compiler.\nIt&#8217;s only when you decide to instantiate the template\n<\/p>\n<pre>\nAbel&lt;Baker&gt; abel;\n<\/pre>\n<p>\nthat these burning questions can be answered,\noverloaded operators can be resolved,\nconversion operators can be hunted down,\nparameters can get pushed on the stack in the correct order,\nand the correct type of <code>call<\/code> instruction can be\ngenerated.\n<\/p>\n<p>\nIn fact, the compiler doesn&#8217;t even care whether or not <code>Baker<\/code>\nhas a <code>Bloober<\/code> method, as long as you never call\n<code>Abel&lt;Baker&gt;::DoBloober<\/code>!\n<\/p>\n<pre>\nvoid f()\n{\n Abel&lt;int&gt; a; \/\/ no error!\n}\nvoid g()\n{\n Abel&lt;int&gt; a;\n a.DoBloober(0, 1); \/\/ error here\n}\n<\/pre>\n<p>Only if you actually call the method does the compiler start looking for\nhow it can generate code for the <code>DoBloober<\/code> method.<\/p>\n<p>\nC# generics aren&#8217;t like that.\n<\/p>\n<p>\nUnlike C++, where a non-instantiated template exists only\nin the imaginary world of potential code that could exist but doesn&#8217;t,\na C# generic results in code being generated,\nbut with placeholders where the type parameter should be inserted.\n<\/p>\n<p>\nThis is why you can use generics implemented in another assembly,\neven without the source code to that generic.\nThis is why a generic can be recompiled without having to recompile\nall the assemblies that use that generic.\nThe code for the generic is generated <i>when the generic is compiled<\/i>.\nBy comparison no code is generated for C++ templates\nuntil the template is instantiated.\n<\/p>\n<p>\nWhat this means for C# generics is that if you want to do something\nwith your type parameter, it has to be something that the compiler\ncan figure out how to do <i>without knowing what <code>T<\/code> is<\/i>.\nLet&#8217;s look at the example that generated today&#8217;s question.\n<\/p>\n<pre>\nclass Foo&lt;T&gt;\n{\n class Bar : T\n { ... }\n}\n<\/pre>\n<p>\nThis is flagged as an error by the compiler:\n<\/p>\n<pre>\nerror CS0689: Cannot derive from 'T' because it is a type parameter\n<\/pre>\n<p>\nDeriving from a generic type parameter is explicitly forbidden by\n25.1.1 of the C# language specification.\nConsider:\n<\/p>\n<pre>\nclass Foo&lt;T&gt;\n{\n class Bar : T\n {\n   public void FlubberMe()\n   {\n     Flubber(0);\n   }\n }\n}\n<\/pre>\n<p>\nThe compiler doesn&#8217;t have enough information to generate the IL for\nthe <code>FlubberMe<\/code> method.\nOne possibility is\n<\/p>\n<pre>\nldarg.0        \/\/ \"this\"\nldc.i4.0    \/\/ integer 0 - is this right?\ncall T.Flubber \/\/ is this the right type of call?\n<\/pre>\n<p>\nThe line <code>ldc.i4.0<\/code> is a guess.\nIf the method <code>T.Flubber<\/code> were actually\n<code>void Flubber(long l)<\/code>,\nthen the line would have to be <code>ldc.i4.0; conv.i8<\/code>\nto load an 8-byte integer onto the stack instead of a 4-byte integer.\nOr perhaps it&#8217;s\n<code>void Flubber(object o)<\/code>,\nin which case the zero needs to be boxed.\n<\/p>\n<p>\nAnd what about that call instruction?\nShould it be a <code>call<\/code> or <code>callvirt<\/code>?\n<\/p>\n<p>\nAnd what if the method returned a value, say,\n<code>string Flubber(int i)<\/code>?\nNow the compiler also has to generate code to discard the\nreturn value from the top of the stack.\n<\/p>\n<p>\nSince the source code for a generic is not included in the assembly,\nall these questions have to be answered at the time the generic is\ncompiled.\nBesides, you can\nwrite a generic in Managed C++ and use it from VB.NET.\nEven saving the source code won&#8217;t be much help if the generic\nwas implemented in a language you don&#8217;t have the compiler for!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A lot of questions about C# generics come from the starting point that they are just a cutesy C# name for C++ templates. But while the two may look similar in the source code, they are actually quite different. C++ templates are macros on steroids. No code gets generated when a template is &#8220;compiled&#8221;; the [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-17093","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A lot of questions about C# generics come from the starting point that they are just a cutesy C# name for C++ templates. But while the two may look similar in the source code, they are actually quite different. C++ templates are macros on steroids. No code gets generated when a template is &#8220;compiled&#8221;; the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17093","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=17093"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17093\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=17093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}