[Mono-list] Base class casting weirdness
Dan Lewis
dihlewis@yahoo.co.uk
17 Jan 2002 23:52:04 +0000
Thanks, Mark! You're right - that's exactly what it was. The wording in
the C# reference manual is a little confusing when talking about the
((A)this).I equivalence, and appears to be very similar to that used in
the Java language specification when discussing its "super" operator -
Java's behaviour is exactly the same as this.
I found a book on Java which said there was no way to access a virtual
method in A from a second derivative class C using the 'super' keyword,
so I'm guessing the same could be said for C# using the 'base' operator.
I don't know whether this is by design or by neglect.
Dan.
On Thu, 2002-01-17 at 05:51, Mark Hurley wrote:
> On Thu, Jan 17, 2002 at 01:13:11AM +0000, Daniel Lewis wrote:
> > Hi,
> >
> > I wonder if anyone can shed light on this. In C#, the 'base' keyword is
> > used to access methods and constructors of base classes:
> >
> > class A {
> > public virtual string Foo () { return "A"; }
> > }
> >
> > class B : A {
> > public override string Foo () { return base.Foo (); }
> > }
> >
> > Invoking Foo on an instance of B returns "A", as you'd expect. The C#
> > programmer's reference that is packaged with the SDK states that:
> >
> > base.Foo ()
> >
> > .. called in an instance method of B is exactly equivalent to writing:
> >
> > ((A)this).Foo ()
> >
>
> I have reason to believe this SDK doc is wrong. Invoking Foo thru the
> "base" [base.Foo()] disables the virtual invocation on A, and treats
> the base method [Foo()] as a non-virtual method.
>
> [((A)this).Foo ()] has the same runtime type of [B.Foo ()]. This
> causes your StackOverflowexception, because B continues to recursively
> invoke itself, not the Foo in A because the one in A is virtual.
>
> This is considered normal behavior, and I read thru two books and the
> MSDN before I found this. :) whew!
>
> If you "hide" B.Foo with something like:
>
> new private string Foo () {}
>
> ...then C can still override A, and you can access A via the
> base-access [base.].
>
> > And that in fact this is what the compiler replaces it with at compile
> > time. But if you try to implement it this way:
>
> Here is sample IL code the compiler generates:
>
> For:
>
> public override string Foo () { return base.Foo (); }
>
> We have this call:
>
> IL_0001: call instance string ConsoleApplication2.A::Foo()
>
> And for this:
>
> public override string Foo () { return ((A)this).Foo(); }
>
> we end up with:
>
> IL_0001: callvirt instance string ConsoleApplication2.A::Foo()
>
> note the difference between [call] and [callvirt]. The latter is used
> to call virtual methods and interface methods, while [call] is used to
> call static and nonvirtual methods.
>
> >
> > public override string Foo () { return ((A)this).Foo (); }
> >
> > CSC will compile it, but you'll get a StackOverflowException at runtime.
> > Why would I want to write it this way instead of using 'base'? Well, I've
> > got a class C derived from B, that wants to implement Foo by invoking A's
> > definition. Can anyone think of a way to do this? Is the runtime
> > exception correct, or is this an SDK bug? And what does MCS/Mono do with
> > this?
>
>
> Mark Hurley
>
>
> _______________________________________________
> Mono-list maillist - Mono-list@ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com