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.