.assembly extern mscorlib {} .assembly OverrideVariance {} .module overridevariance.exe .class public A extends [mscorlib]System.Object { .method public specialname rtspecialname instance void .ctor() cil managed { .maxstack 1 ldarg.0 call instance void [mscorlib]System.Object::.ctor() ret } .method public newslot virtual instance object Method() cil managed { .maxstack 1 // return new object(); newobj instance void [mscorlib]System.Object::.ctor() ret } } .class public B extends A { .method public specialname rtspecialname instance void .ctor() cil managed { .maxstack 1 ldarg.0 call instance void A::.ctor() ret } // This is a completely different method to A.Method() .method public virtual instance string Method() cil managed { .maxstack 1 // return String.Empty; ldsfld string [mscorlib]System.String::Empty ret } } .class public Program extends [mscorlib]System.Object { .method private static void Main() cil managed { .entrypoint // call A.Method() on an instance of A ldstr "Calling A.Method on A: " call void [mscorlib]System.Console::Write(string) newobj instance void A::.ctor() callvirt instance object A::Method() call void Program::Output(object) // call B.Method() on an instance of B ldstr "Calling B.Method on B: " call void [mscorlib]System.Console::Write(string) newobj instance void B::.ctor() callvirt instance string B::Method() call void Program::Output(object) // call A.Method() on an instance of B ldstr "Calling A.Method on B: " call void [mscorlib]System.Console::Write(string) newobj instance void B::.ctor() castclass A callvirt instance object A::Method() call void Program::Output(object) ret } .method private static void Output(object obj) cil managed { .maxstack 1 // Console.WriteLine(obj.GetType()); ldarg.0 callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType() callvirt instance string [mscorlib]System.Object::ToString() call void [mscorlib]System.Console::WriteLine(string) ret } }