title: Why is 'box' instruction emitted for generic?
body: <p>Here is fairly simple generic class. Generic parameter is constrained to be reference type. <code>IRepository</code> and <code>DbSet</code> also contain the same constraint.</p>
  
  <pre><code>public class Repository&lt;TEntity&gt; : IRepository&lt;TEntity&gt;
      where TEntity : class, IEntity
  {
      protected readonly DbSet&lt;TEntity&gt; _dbSet;
      public void Insert(TEntity entity)
      {
          if (entity == null) 
          throw new ArgumentNullException("entity", "Cannot add null entity.");
          _dbSet.Add(entity);
      }
  }
  </code></pre>
  
  <p>Compiled IL contains <code>box</code> instruction. Here is the release version (debug version also contains it though).</p>
  
  <pre><code>.method public hidebysig newslot virtual final 
      instance void  Insert(!TEntity entity) cil managed
  {
    // Code size       38 (0x26)
    .maxstack  8
    IL_0000:  ldarg.1
    &gt;&gt;&gt;IL_0001:  box        !TEntity
    IL_0006:  brtrue.s   IL_0018
    IL_0008:  ldstr      "entity"
    IL_000d:  ldstr      "Cannot add null entity."
    IL_0012:  newobj     instance void [mscorlib]System.ArgumentNullException::.ctor(string,
                                             string)
    IL_0017:  throw
    IL_0018:  ldarg.0
    IL_0019:  ldfld      class [EntityFramework]System.Data.Entity.DbSet`1&lt;!0&gt; class Repository`1&lt;!TEntity&gt;::_dbSet
    IL_001e:  ldarg.1
    IL_001f:  callvirt   instance !0 class [EntityFramework]System.Data.Entity.DbSet`1&lt;!TEntity&gt;::Add(!0)
    IL_0024:  pop
    IL_0025:  ret
  } // end of method Repository`1::Insert
  </code></pre>
  
  <p><strong>UPDATE:</strong> </p>
  
  <p>With <code>object.Equals(entity, default(TEntity))</code> it looks even worse:</p>
  
  <pre><code>  .maxstack  2
    .locals init ([0] !TEntity CS$0$0000)
    IL_0000:  ldarg.1
    &gt;&gt;&gt;IL_0001:  box        !TEntity
    IL_0006:  ldloca.s   CS$0$0000
    IL_0008:  initobj    !TEntity
    IL_000e:  ldloc.0
    &gt;&gt;&gt;IL_000f:  box        !TEntity
    IL_0014:  call       bool [mscorlib]System.Object::Equals(object,
                                  object)
    IL_0019:  brfalse.s  IL_002b
  </code></pre>
  
  <p><strong>UPDATE2:</strong></p>
  
  <p>For those who are interested, here is the code compiled by jit shown in debugger:</p>
  
  <pre><code>0cd5af28 55              push    ebp
  0cd5af29 8bec            mov     ebp,esp
  0cd5af2b 83ec18          sub     esp,18h
  0cd5af2e 33c0            xor     eax,eax
  0cd5af30 8945f0          mov     dword ptr [ebp-10h],eax
  0cd5af33 8945ec          mov     dword ptr [ebp-14h],eax
  0cd5af36 8945e8          mov     dword ptr [ebp-18h],eax
  0cd5af39 894df8          mov     dword ptr [ebp-8],ecx
      //entity reference to [ebp-0Ch]
  0cd5af3c 8955f4          mov     dword ptr [ebp-0Ch],edx
      //some debugger checks
  0cd5af3f 833d9424760300  cmp     dword ptr ds:[3762494h],0
  0cd5af46 7405            je      0cd5af4d  Branch
  0cd5af48 e8e1cac25a      call    clr!JIT_DbgIsJustMyCode (67987a2e)
  0cd5af4d c745fc00000000  mov     dword ptr [ebp-4],0
  0cd5af54 90              nop
  
      //comparison or entity ref with  zero
  0cd5af55 837df400        cmp     dword ptr [ebp-0Ch],0
  0cd5af59 0f95c0          setne   al
  0cd5af5c 0fb6c0          movzx   eax,al
  0cd5af5f 8945fc          mov     dword ptr [ebp-4],eax
  0cd5af62 837dfc00        cmp     dword ptr [ebp-4],0
      //if not zero, jump further
  0cd5af66 7542            jne     0cd5afaa  Branch
      //throwing exception here      
  </code></pre>
  
  <p>The reason of this question is actually that NDepend warns about using boxing/unboxing. I was curious why it found boxing in some generic classes, and now it's clear.</p>