Why does Int32.ToString () emit a call command instead of callvirt?

For the following code snippet:

struct Test
{
    public override string ToString()
    {
        return "";
    }
}

public class Program
{
    public static void Main()
    {
        Test a = new Test();
        a.ToString();
        Int32 b = 5;
        b.ToString();
    }
}

The compiler emits the following IL:

  .locals init ([0] valuetype ConsoleApplication2.Test a,
           [1] int32 b)
  IL_0000:  nop
  IL_0001:  ldloca.s   a
  IL_0003:  initobj    ConsoleApplication2.Test
  IL_0009:  ldloca.s   a
  IL_000b:  constrained. ConsoleApplication2.Test
  IL_0011:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_0016:  pop
  IL_0017:  ldc.i4.5
  IL_0018:  stloc.1
  IL_0019:  ldloca.s   b
  IL_001b:  call       instance string [mscorlib]System.Int32::ToString()
  IL_0020:  pop
  IL_0021:  ret

Since both types of values Testand Int32override the method ToString(), I think that none of boxing will not occur in a.ToString(), and in b.ToString(). So I wonder why the compiler emits constraned+ callvirtfor Testand callfor Int32?

+4
source share
2 answers

This is an optimization performed by the compiler for primitive types.

callvirt call - constrained. - , . , .

MSDN:

thisType - , thisType method, ptr this call, thisType.

constrained IL , ptr . , thisType , , .

, Roslyn MayUseCallForStructMethod.

, - , , . , , ToString, DLL ( !) , . . , .

+6

, Int , , , - int ToString, , ToString(), Int, callvirt, , .

, ToString , , , , , , , Object, callvirt, ToString(), , , , .

SO :

Call and Callvirt

0

Source: https://habr.com/ru/post/1649640/


All Articles