Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy is 'box' instruction emitted for generic?
    primarykey
    data
    text
    <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>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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