[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
>