PC Review


Reply
Thread Tools Rate Thread

Do *this* pointer breaks overriding implementation?

 
 
=?Utf-8?B?RXJpYyBDaGF2ZXM=?=
Guest
Posts: n/a
 
      13th Jan 2004
Hi fellows,

According to the C# language specification (10.5.3), Every virtual method has a "most derived implementation" determined by a 3-step rule. If I invoke the virtual method from a normal variable, everything is ok. However if I call it inside a non-virtual method from the base class, that use's the *this*pointer to actually invoke the virtual method, then those rules doesn't seems to be respected. In fact, the behavior the code below (ilustrating the problem) induces me to belive that the *this* pointer is always resolved as compile-time type, when it should be run-time type (otherwise how could it access the the correct properties in polimorphic calls).

What am I missing here?


----
using System;

class A
{
public void G(){this.F();}
public virtual void F(){Console.WriteLine("A.F");}
}
class B:A
{
public virtual void F(){Console.WriteLine("B.F");}
}
class C:B
{
public virtual void F(){Console.WriteLine("C.F");}
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
C t = new C();
A a = t;
B b = t;
C c = t;
// the first tree calls are ok with the C# language
// specification for "most derived implementation" rule (10.5.3 Virtual methods)
a.F();
b.F();
c.F();
// The use of *this* pointer inside the G function
//breaks the most derived implementation rule.
a.G();
b.G();
c.G();
}
}

 
Reply With Quote
 
 
 
 
Mattias Sjögren
Guest
Posts: n/a
 
      13th Jan 2004
Eric,

>
> According to the C# language specification (10.5.3), Every virtual method has a "most derived implementation" determined by a 3-step rule. If I invoke the virtual method from a normal variable, everything is ok. However if I call it inside a non-virtual method from the base class, that use's the *this*pointer to actually invoke the virtual method, then those rules doesn't seems to be respected. In fact, the behavior the code below (ilustrating the problem) induces me to belive that the *this* pointer is always resolved as compile-time type, when it should be run-time type (otherwise how could it access the the correct properties in polimorphic calls).
>
>What am I missing here?


It's not the use of "this" that breaks polymorphism, it's the lack of
the override keyword on the derived implementations. You should get
CS0114 warnings when you compile the code informing you about this. To
get the behavior you want, change

public virtual void F(){Console.WriteLine("B.F");}

to

public override void F(){Console.WriteLine("B.F");}

and do the same in class C.



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
 
Reply With Quote
 
=?Utf-8?B?RXJpYyBDaGF2ZXM=?=
Guest
Posts: n/a
 
      14th Jan 2004
Hi Mattias

Thanks for the reply, but I'm still lost. If I use the override on descendent class (for example, if I override the F method in B class), then when I try to invoke a typecast on a variable (the first 3 calls of the code. ie: a.F(), b.F()) the code will always execute the B.F() method, and descendent classes will lost the ability to "behave" as A class. I'm not very expericend with OOP (and for that, I might be saying a foolish here ) but isn't this "behave as" the polimorphic behavior

Also, the 10.5.3 Virtual methods C# language states:
"The most derived implementation of a virtual method M with respect to a class R is determined as follows:

- If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
- Otherwise, if R contains an override of M, then this is the most derived implementation of M.
- Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.


If I use the "new virtual" keywords, I keep the polimorphic behavior on the first 3 calls of my code, but 3 subsequent calls of G() all resolve to A.F(). In other words

class A
public void G(){this.F();
public virtual void F(){Console.WriteLine("A.F");

class B:A{ new public virtual void F(){Console.WriteLine("B.F");}
class C:B{ new public virtual void F(){Console.WriteLine("C.F");}

when I call

C c = new C()
A a = c
a.G()

the compiler should enter A.G, evalueate this.F(), found that F is virtual and the runtime type of the class is C (this = C) and then since C.F has the virual keyword, shouldn't it be resolved as the most derived method and takes place

Is it possible (and if so, how) to make the code below produces the following output
A.
B.
C.
A.
B.
C.


using System

class

public void G(){F();
public virtual void F(){Console.WriteLine("A.F");

class B:A { new public virtual void F(){Console.WriteLine("B.F");}
class C:B { new public virtual void F(){Console.WriteLine("C.F");}
class Class

[STAThread
static void Main(string[] args

C t = new C()
A a = t
B b = t
C c = t
// the first tree calls are ok with the C# language
// specification for "most derived implementation" rule (10.5.3 Virtual methods
a.F()
b.F()
c.F()
// The use of *this* pointer inside the G function
// breaks the most derived implementation rule
a.G();
b.G();
c.G();



Thanks again for the help. Cheers

Eric

 
Reply With Quote
 
Mattias Sjögren
Guest
Posts: n/a
 
      15th Jan 2004
Eric,

>If I use the override on descendent class (for example, if I override the F method in B class),
>then when I try to invoke a typecast on a variable (the first 3 calls of the code. ie: a.F(),
>b.F()) the code will always execute the B.F() method,


Right, if B.F overrides the virtual A.F, and B has the most derived
implementation of the method, B.F will run. That's the polymorphic
behavior you want with using virtual methods.


>and descendent classes will lost the ability to "behave" as A class.


Not sure what you mean there. You should be able to use an instance of
B wherever an instance of A is required.


>the compiler should enter A.G, evalueate this.F(), found that F is virtual and the runtime type of the class
>is C (this = C) and then since C.F has the virual keyword, shouldn't it be resolved as the most derived
>method and takes place?


No, using "new" is a way to explicitly say that you don't want C.F to
override A.F. C.F is a whole new method that is unrelated to A.F, they
just happen to have the same name.

So the most derived version of F that's called from A.G is A.F itself,
since B.F is a new method, not overriding A.F.


>Is it possible (and if so, how) to make the code below produces the following output?
>A.F
>B.F
>C.F
>A.F
>B.F
>C.F


If you add

public new void G(){F();}

to B and C.



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
my code breaks unique pointer rule? George3 Microsoft VC .NET 1 15th Feb 2008 04:51 PM
Generic implementation of a smart pointer software@werthmesstechnik.de Microsoft VC .NET 2 9th Oct 2007 05:13 PM
overriding C runtime functions with my own implementation Jonathan Wilson Microsoft VC .NET 3 18th Jan 2007 03:45 AM
Overriding == and != when overriding Equals()? Kenneth Baltrinic Microsoft C# .NET 3 9th May 2006 02:02 PM
Do *this* pointer breaks overriding implementation? =?Utf-8?B?RXJpYyBDaGF2ZXM=?= Microsoft C# .NET 3 15th Jan 2004 06:39 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 06:23 PM.