Why is an explicit interface method called with callvirt and not implicitly implemented?

Why callvirtdoes the compiler generate a command to call the method of the explicitly implemented interface and callto call the method of the implemented interface implicilty in the following code?

The compiler was mono mcs4.2.2 with optimization enabled.

public interface ITest
{
  void ExplicitInterfaceMethod();
  void ImplicitInterfaceMethod();
}

public sealed class Test : ITest
{
  void ITest.ExplicitInterfaceMethod()
  { }

  public void ImplicitInterfaceMethod()
  { }

  public void InstanceMethod()
  { }

  public void CallTest()
  {
    ((ITest) this).ExplicitInterfaceMethod();
    // IL_0000:  ldarg.0 
    // IL_0001:  callvirt instance void class ITest::ExplicitInterfaceMethod()

    this.ImplicitInterfaceMethod();
    // IL_0006:  ldarg.0 
    // IL_0007:  call instance void class Test::ImplicitInterfaceMethod()

    InstanceMethod();
    // IL_000c:  ldarg.0 
    // IL_000d:  call instance void class Test::InstanceMethod()
  }
}

What I have found out so far:

  • callvirtused for a "receiver with a null value" because it performs a null check before fixing a jump to a method. It seems thisto be null. ( Call and Callvirt )
  • call used if the compiler can prove that the receiver is not zero.
  • , callvirt, . ( .)

, this , .

? this null?

, - , . , this null , call ?

@jonathon-chase , : , , "", / . , callvirt, . (. ).

:

sealed, . , 1) , 2) this, 3) - sealed; . , call, , , .

+4
1

, , . , , .

, ildasm.exe /target: library/optimize + csc. , , . , , . - , , .

:

using System;

public interface ITest
{
  void TestMethod();
}

public class Test : ITest
{
  void ITest.TestMethod()
  {
    Console.WriteLine("I am Test");
  }

  void TestMethod()
  {
    Console.WriteLine("I am other test");
  }
}

IL:

.class interface public abstract auto ansi ITest
{
  .method public hidebysig newslot abstract virtual 
          instance void  TestMethod() cil managed
  {
  } // end of method ITest::TestMethod

} // end of class ITest

.class public auto ansi beforefieldinit Test
       extends [mscorlib]System.Object
       implements ITest
{
  .method private hidebysig newslot virtual final 
          instance void  ITest.TestMethod() cil managed
  {
    .override ITest::TestMethod
    // Code size       11 (0xb)
    .maxstack  8
    IL_0000:  ldstr      "I am Test"
    IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000a:  ret
  } // end of method Test::ITest.TestMethod

  .method private hidebysig instance void 
          TestMethod() cil managed
  {
    // Code size       11 (0xb)
    .maxstack  8
    IL_0000:  ldstr      "I am other test"
    IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000a:  ret
  } // end of method Test::TestMethod
+3

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


All Articles