[Mono-list] Base class casting weirdness
Mark Hurley
debian4tux@telocity.com
Sat, 19 Jan 2002 20:51:12 -0500
On Thu, Jan 17, 2002 at 11:52:04PM +0000, Dan Lewis wrote:
> 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.
No problem...I had a lot of fun investigating it! ;)
> 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.
What I've read and my best determination (writing can be wrong ;)) ...this
is by DESIGN.
Mark Hurley
>
> 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
>
>
> _______________________________________________
> Mono-list maillist - Mono-list@ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
>