Explicit Method Overriding

Explicit Method Overriding

Thus far, I’ve discussed implicit virtual method overriding—that is, a virtual method defined in a class overriding another virtual method of the same name and signature, defined in the class’s ancestor or an interface the class implements. But implicit overriding covers only the simplest case.

Consider the following problem: class A implements interfaces IX and IY, and each of these interfaces defines its own virtual method int32 Foo(int32). It is known that these methods are different and must be implemented separately. Implicit overriding can’t help in this situation. It’s time to use the MethodImpl metadata table.

The MethodImpl metadata table contains descriptors of explicit method overrides. An explicit override states which method overrides which other method. To define an explicit override in ILAsm, the following directive is used within the scope of the overriding method:

.override <class_ref>::<method_name>

The signature of the method need not be specified because the signature of the overriding method must match the signature of the overridden method, and the signature of the overriding method is known: it’s the signature of the current method. For example:

.class public interface IX {    .method public abstract virtual int32 Foo(int32) { } } .class public interface IY {    .method public abstract virtual int32 Foo(int32) { } } .class public implements IX,IY {    .method public virtual int32 XFoo(int32) {       .override IX::Foo            }    .method public virtual int32 YFoo(int32) {       .override IY::Foo            } }

Not surprisingly, we can’t override the same method with two different methods within the same class: there is only one slot in the v-table to be overridden. However, we can use the same method to override several virtual methods. Let’s have a look at the following code from the sample file Override.il on the companion CD:

.class public A {    .method public specialname void .ctor() { ret }    .method public void Foo()    {       ldstr "A::Foo"       call void [mscorlib]System.Console::WriteLine(string)       ret    }    .method public virtual void Bar()    {       ldstr "A::Bar"       call void [mscorlib]System.Console::WriteLine(string)       ret    }    .method public virtual void Baz()    {       ldstr "A::Baz"       call void [mscorlib]System.Console::WriteLine(string)       ret    } } .class public extends A {    .method public specialname void .ctor() { ret }    .method public void Foo()    {       ldstr "B::Foo"       call void [mscorlib]System.Console::WriteLine(string)       ret    }    .method public virtual void BarBaz()    {       .override A::Bar       .override A::Baz       ldstr "B::BarBaz"       call void [mscorlib]System.Console::WriteLine(string)       ret    } }  .method public static void Exec() {    .entrypoint    newobj instance void B::.ctor() // Create instance of derived class    castclass class A           // Cast it to base class    dup                 // We need 3 instance pointers    dup                 // On stack for 3 calls    call instance void A::Foo()    callvirt instance void A::Bar()    callvirt instance void A::Baz()        ret}

The output of this code demonstrates that the method B::BarBaz overrides both A::Bar and A::Baz:

A::Foo B::BarBaz B::BarBaz

Virtual method overriding, both implicit and explicit, is propagated to the descendants of the overriding class, unless the descendants themselves override those methods. The second half of the sample file Override.il demonstrates this:

 .class public extends B {    .method public specialname void .ctor() { ret }    // No overrides; let's inherit everything from B } .method public static void Exec() {    .entrypoint        newobj instance void C::.ctor() // Create instance of derived class    castclass class A           // Cast it to "grandparent"    dup                 // We need 3 instance pointers    dup                 // On stack for 3 calls    call instance void A::Foo()    callvirt instance void A::Bar()    callvirt instance void A::Baz()    Ret }

The output is the same, which proves that class C has inherited the overridden methods from class B:

A::Foo B::BarBaz B::BarBaz

ILAsm supports an extended form of the explicit override directive, placed within the class scope:

.override <class_ref>::<method_name> with <method_ref>

For example, the overriding effect would be the same in the preceding code if we defined class B like so:

.class public extends A {    .method public specialname void .ctor() { ret }    .method public void Foo()    {       ldstr "B::Foo"       call void [mscorlib]System.Console::WriteLine(string)       ret    }    .method public virtual void BarBaz()    {       ldstr "B::BarBaz"       call void [mscorlib]System.Console::WriteLine(string)       ret    }    .override A::Bar with instance void B::BarBaz()    .override A::Baz with instance void B::BarBaz() }

In the extended form of the .override directive, the overriding method must be fully specified because the extended form is used within the overriding class scope, not within the overriding method scope.

To tell the truth, the extended form of the .override directive is not very useful in the first version of the common language runtime because the overriding methods are restricted to those of the overriding class. Under these circumstances, the short form of the directive is sufficient, and I doubt that anyone would want to use the more cumbersome extended form. But I’ve noticed that in this industry the circumstances tend to change.



Inside Microsoft. NET IL Assembler
Inside Microsoft .NET IL Assembler
ISBN: 0735615470
EAN: 2147483647
Year: 2005
Pages: 147
Authors: SERGE LIDIN

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net