This is a deficiency in the current version of the Loader -- explicit overrides 
(through MethodImpls) cannot be chained. At the same time, implicit overrides can be 
chained alright, which creates an assymetry between explicit and implicit overrides. 

Partition II says nothing about limitations on explicit override chaining, which 
implies there should be no such limitations. The only limitation specified in 
Partition II is that the same v-table slot can't be overridden with more than one 
method, and in the case Brent is citing this doesn't happen.

Clearly, this deficiency needs fixing. And I extend our profound thanks to Brent, The 
Intrepid Vigilante of Partition II and Surrounding Territories!

--Serge

-----Original Message-----
From: Brent E. Rector [mailto:[EMAIL PROTECTED]]
Sent: Monday, May 20, 2002 2:25 PM
To: [EMAIL PROTECTED]
Subject: [DOTNET] Partition II Metadata Spec question


I cannot figure out how to use MethodImpl's to override a virtual method
when I have multiple levels of inheritance using MethodImpl's. Let's
start with a simple C# example:

internal class Base {
     public override string ToString () { return "Base"; }
}

internal class Derived : Base {
     public override string ToString () { return "Derived"; }
}

internal class MoreDerived : Derived {
     public override string ToString () { return "MoreDerived"; }
}

internal class App {
    static void Main () {
       MoreDerived m = new MoreDerived ();
       Derived     d = m;
       Base        b = m;
       object      o = m;

       System.Console.WriteLine ("Object.ToString() returns " +
o.ToString());
       System.Console.WriteLine ("Base.ToString() returns " +
b.ToString());
       System.Console.WriteLine ("Derived.ToString() returns " +
d.ToString());
       System.Console.WriteLine ("MoreDerived.ToString() returns " +
m.ToString());
    }
}

Given the above class hierarchy, running the program produces the
following expected output:

Object.ToString() returns MoreDerived
Base.ToString() returns MoreDerived
Derived.ToString() returns MoreDerived
MoreDerived.ToString() returns MoreDerived

Now, let's rename the Base.ToString method to Base.Foo but still have it
override System.Object.ToString. A quick ILDASM, a change to the Base
class and reassemble:

.class private auto ansi beforefieldinit Base
       extends [mscorlib]System.Object
{
  .method public hidebysig virtual instance string 
          Foo() cil managed
  {
    <snip>

  } // end of method Base::ToString

  .override [mscorlib]System.Object::ToString with instance string
Base::Foo()

<snip>

} // end of class Base

I run the modified program and get the same, expected output:

Object.ToString() returns MoreDerived
Base.ToString() returns MoreDerived
Derived.ToString() returns MoreDerived
MoreDerived.ToString() returns MoreDerived


Now, the problem I cannot seem to solve: I now want to modify the
Derived class so that it has a method called 'Bar' that overrides
Base.ToString. Of course, Base.ToString doesn't really exist, but
Base.Foo exists and it's its implementation I really want to override.
So I change the definition of Derived like so:

.class private auto ansi beforefieldinit Derived
       extends Base
{
  .method public hidebysig virtual instance string 
          Bar() cil managed
  {
    <snip>
  } // end of method Derived::ToString

  .override Base::Foo with instance string Derived::Bar()

<snip>

} // end of class Derived

Now the program won't load due to a TypeLoadException:

Unhandled Exception: System.TypeLoadException: Method Foo on type
Derived from assembly Foo is overriding a method impl.
   at App.Main()

(Yes, the error message itself is a little wrong but that's an unrelated
problem.) So I figure conceptually I want to override Base.ToString so I
changed the .override to:

  .override Base::ToString with instance string Derived::Bar()

But I still get the same exception:

Unhandled Exception: System.TypeLoadException: Method Foo on type
Derived from assembly Foo is overriding a method impl.
   at App.Main()

So finally, I changed the .override to:

  .override [mscorlib]System.Object::ToString with instance string
Derived::Bar()

Now the program loads and runs but the output isn't what I expected or
want:

Object.ToString() returns MoreDerived
Base.ToString() returns Base
Derived.ToString() returns MoreDerived
MoreDerived.ToString() returns MoreDerived

Basically, the question becomes how can I make Derived::Bar use the same
vtbl slot as Base::Foo which itself is using the same vtbl slot as
System.Object::ToString?

-- Brent Rector, .NET Wise Owl
Demeanor for .NET - an obfuscation utility
http://www.wiseowl.com/Products/Products.aspx

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to