{"id":3189,"date":"2010-11-17T18:50:00","date_gmt":"2010-11-17T18:50:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/subterranean-il-constructor-constraints\/"},"modified":"2021-04-29T15:30:55","modified_gmt":"2021-04-29T15:30:55","slug":"subterranean-il-constructor-constraints","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/subterranean-il-constructor-constraints\/","title":{"rendered":"Subterranean IL: Constructor constraints"},"content":{"rendered":"<p>The constructor generic constraint is a slightly wierd one. The ECMA specification simply states that it: <\/p>\n<p>constrains [the type] to being a concrete reference type (i.e., not abstract) that has a public constructor taking no arguments (the default constructor), or to being a value type. There seems to be no reference within the spec to how you actually create an instance of a generic type with such a constraint. In non-generic methods, the normal way of creating an instance of a class is quite different to initializing an instance of a value type. For a reference type, you use <code>newobj<\/code>: <\/p>\n<pre>newobj instance void IncrementableClass::.ctor()<\/pre>\n<p> and for value types, you need to use <code>initobj<\/code>: <\/p>\n<pre>.locals init ( valuetype IncrementableStruct s1 )\n\nldloca 0\ninitobj IncrementableStruct<\/pre>\n<p> But, for a generic method, we need a consistent method that would work equally well for reference or value types.<\/p>\n<p><b><code>Activator.CreateInstance&lt;T&gt;<\/code><\/b><\/p>\n<p>To solve this problem the CLR designers could have chosen to create something similar to the <code>constrained.<\/code> prefix; if <code>T<\/code> is a value type, call <code>initobj<\/code>, and if it is a reference type, call <code>newobj instance void !!0::.ctor()<\/code>.<\/p>\n<p>However, this solution is much more heavyweight than <code>constrained callvirt<\/code>. The <code>newobj<\/code> call is encoded in the assembly using a simple reference to a row in a metadata table. This encoding is no longer valid for a call to <code>!!0::.ctor()<\/code>, as different constructor methods occupy different rows in the metadata tables. Furthermore, constructors aren&#8217;t virtual, so we would have to somehow do a dynamic lookup to the correct method at runtime without using a MethodTable, something which is completely new to the CLR. Trying to do this in IL results in the following verification error: <\/p>\n<pre>newobj instance void !!0::.ctor()\n\n[IL]: Error: Unable to resolve token.<\/pre>\n<\/p>\n<p>This is where <code>Activator.CreateInstance&lt;T&gt;<\/code> comes in. We can call this method to return us a new <code>T<\/code>, and make the whole issue Somebody Else&#8217;s Problem. <code>CreateInstance<\/code> does all the dynamic method lookup for us, and returns us a new instance of the correct reference or value type (strangely enough, <code>Activator.CreateInstance&lt;T&gt;<\/code> does not itself have a <code>.ctor<\/code> constraint on its generic parameter): <\/p>\n<pre>.method private static !!0 CreateInstance&lt;.ctor T&gt;() {\n    call !!0 [mscorlib]System.Activator::CreateInstance&lt;!!0&gt;()\n    ret\n}<\/pre>\n<p><b>Going further: compiler enhancements<\/b><\/p>\n<p>Although this method works perfectly well for solving the problem, the C# compiler goes one step further. If you decompile the C# version of the <code>CreateInstance<\/code> method above: <\/p>\n<pre>private static T CreateInstance() where T : new() {\n    return new T();\n}<\/pre>\n<p> what you actually get is this (edited slightly for space &amp; clarity): <\/p>\n<pre>.method private static !!T CreateInstance&lt;.ctor T&gt;() {\n    .locals init (\n        [0] !!T CS$0$0000,\n        [1] !!T CS$0$0001\n    )\n    \n  DetectValueType:\n    ldloca.s 0\n    initobj !!T\n    ldloc.0\n    box !!T\n    brfalse.s CreateInstance\n    \n  CreateValueType:\n    ldloca.s 1\n    initobj !!T\n    ldloc.1\n    ret\n    \n  CreateInstance:\n    call !!0 [mscorlib]System.Activator::CreateInstance&lt;T&gt;()\n    ret\n}<\/pre>\n<p> What on earth is going on here? Looking closer, it&#8217;s actually quite a clever performance optimization around value types. So, lets dissect this code to see what it does.<\/p>\n<p>The <code>CreateValueType<\/code> and <code>CreateInstance<\/code> sections should be fairly self-explanatory; using <code>initobj<\/code> for value types, and <code>Activator.CreateInstance<\/code> for reference types. How does the <code>DetectValueType<\/code> section work?<\/p>\n<p>First, the stack transition for value types: <\/p>\n<pre>ldloca.s 0     \/\/ &amp;[!!T(uninitialized)]\ninitobj !!T    \/\/\nldloc.0        \/\/ !!T\nbox !!T        \/\/ O[!!T]\nbrfalse.s      \/\/ branch not taken<\/pre>\n<p> When the <code>brfalse.s<\/code> is hit, the top stack entry is a non-null reference to a boxed <code>!!T<\/code>, so execution continues to to the <code>CreateValueType<\/code> section.<\/p>\n<p>What about when <code>!!T<\/code> is a reference type? Remember, the &#8216;default&#8217; value of an object reference (type <code>O<\/code>) is zero, or null. <\/p>\n<pre>ldloca.s 0     \/\/ &amp;[!!T(null)]\ninitobj !!T    \/\/\nldloc.0        \/\/ null\nbox !!T        \/\/ null\nbrfalse.s      \/\/ branch taken<\/pre>\n<p> Because <code>box<\/code> on a reference type is a no-op, the top of the stack at the <code>brfalse.s<\/code> is null, and so the branch to <code>CreateInstance<\/code> is taken.<\/p>\n<p>For reference types, <code>Activator.CreateInstance<\/code> is called which does the full dynamic lookup using reflection. For value types, a simple <code>initobj<\/code> is called, which is far faster, and also eliminates the unboxing that <code>Activator.CreateInstance<\/code> has to perform for value types. However, this is strictly a performance optimization; <code>Activator.CreateInstance&lt;T&gt;<\/code> works for value types as well as reference types.<\/p>\n<p><b>Next&#8230;<\/b><\/p>\n<p>That concludes the initial premise of the Subterranean IL series; to cover the details of generic methods and generic code in IL. I&#8217;ve got a few other ideas about where to go next; however, if anyone has any itching questions, suggestions, or things you&#8217;ve always wondered about IL, do let me know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The constructor generic constraint is a slightly wierd one. The ECMA specification simply states that it: constrains [the type] to being a concrete reference type (i.e., not abstract) that has a public constructor taking no arguments (the default constructor), or to being a value type. There seems to be no reference within the spec to&#8230;&hellip;<\/p>\n","protected":false},"author":186659,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,2],"tags":[],"coauthors":[],"class_list":["post-3189","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3189","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/186659"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3189"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3189\/revisions"}],"predecessor-version":[{"id":41962,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3189\/revisions\/41962"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3189"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3189"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3189"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3189"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}