Non-virtual methods - why?

  • Thread starter Thread starter Adrian Herscu
  • Start date Start date
A

Adrian Herscu

Hi all,

In which circumstances it is appropriate to declare methods as non-virtual?

Thanx,
Adrian.
 
Adrian Herscu said:
Hi all,

In which circumstances it is appropriate to declare methods as
non-virtual?
Any time that a) security could be comprimised, b)stability could be
comprimised, c) its not possible to write a method that cannot be overriden
safely(related to a &b both).
 
Anytime you want that the base class method to remain unchanged by
overwriting it in inheritors.
:) I presume you came from Java where all the methods are virtual by
default, anyway it adds some clarity to the code.
 
Adrian Herscu said:
In which circumstances it is appropriate to declare methods as non-virtual?

Well, they're non-virtual by default, normally. The only time when you
need to make them specifically non-virtual is when you're overriding a
virtual method, but you don't want anyone to override your
implementation.
 
Horatiu Ripa said:
Anytime you want that the base class method to remain unchanged by
overwriting it in inheritors.
:) I presume you came from Java where all the methods are virtual by
default, anyway it adds some clarity to the code.

You almost guess it right! I learn Java a few days before, and it says that
it is C++ cleaned up. As far as I remember, C++ has virtual and non-virtual
method declarations and now I see that C# continued that tradition. But, I
want to understand the essence of it - why non-virtual methods are needed?
Java is used almost ten years without non-virtual methods and nobody
complains about!
 
Adrian Herscu said:
You almost guess it right! I learn Java a few days before, and it says that
it is C++ cleaned up. As far as I remember, C++ has virtual and non-virtual
method declarations and now I see that C# continued that tradition. But, I
want to understand the essence of it - why non-virtual methods are needed?
Java is used almost ten years without non-virtual methods and nobody
complains about!

Java *does* have non-virtual methods (they're called final in Java).
Look at Object.wait() for example.
 
One common use is with the "Template Method" pattern:
the base class declares a public non-virtual function which
checks preconditions, calls a protected or private virtual
function, then checks postconditions, like so:

(F is non-virtual, DoF is protected virtual and probably abstract)

int base::F(int i)
{
int ret;
if (IsParamInRange(i))
ret = DoF(i);
if (IsRetInRange(ret))
return ret;
else
return someError;
}

The idea is to force everyone to use a common "entry point"
to some functionality with derived classes implementing specific
tasks.

Andrew
 
Jon Skeet said:
Java *does* have non-virtual methods (they're called final in Java).
Look at Object.wait() for example.

I think you are wrong. Read the Java Language Specification, para 8.4.3.3:
"A method can be declared final to prevent subclasses from overriding or
hiding it. It is a compile-time error to attempt to override or hide a final
method".

A final method in Java is close to a sealed method in C# - it prevents
further overriding.
In Java, methods can be hidden only by static methods - so, Java has no
concept of non-virtual methods.
While in C#, methods can be hidden because they were not marked virtual -
so, in order to be sealed a method has to be virtual.
 
That's interesting - other examples?

andrew queisser said:
One common use is with the "Template Method" pattern:
the base class declares a public non-virtual function which
checks preconditions, calls a protected or private virtual
function, then checks postconditions, like so:

(F is non-virtual, DoF is protected virtual and probably abstract)

int base::F(int i)
{
int ret;
if (IsParamInRange(i))
ret = DoF(i);
if (IsRetInRange(ret))
return ret;
else
return someError;
}

The idea is to force everyone to use a common "entry point"
to some functionality with derived classes implementing specific
tasks.

Andrew
 
Adrian Herscu said:
I think you are wrong. Read the Java Language Specification, para 8.4.3.3:
"A method can be declared final to prevent subclasses from overriding or
hiding it. It is a compile-time error to attempt to override or hide a final
method".

A final method in Java is close to a sealed method in C# - it prevents
further overriding.

And that, as far as I'm concerned, is the principal feature of being
non-virtual.
In Java, methods can be hidden only by static methods - so, Java has no
concept of non-virtual methods.

No, it has no concept of instance methods hiding other instance
methods, which I view as being separate from having no concept of non-
virtual methods.
While in C#, methods can be hidden because they were not marked virtual -
so, in order to be sealed a method has to be virtual.

In my view, they can be sealed to prevent them being virtual any
further.

My way of looking at things is that something is virtual if it can be
overridden, and is non-virtual if it can't.

It's all a matter of definition, of course, but mine seems to fit in
pretty well with this section from the MSDN on virtual members:

<quote>
The virtual keyword is used to modify a method or property declaration,
in which case the method or the property is called a virtual member.
The implementation of a virtual member can be changed by an overriding
member in a derived class.

When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member. (For more information on run-
time type and most derived implementation, see 10.5.3 Virtual methods.)

By default, methods are non-virtual. You cannot override a non-virtual
method.
</quote>

Here's another one, from the C# language specification:

<quote>
The implementation of a non-virtual method is invariant: The
implementation is the same whether the method is invoked on an instance
of the class in which it is declared or an instance of a derived class.
In contrast, the implementation of a virtual method can be superseded
by derived classes.
</quote>

A final method in Java absolutely satisfies the descriptions of non-
virtual methods above. Note that in neither of those two quotes is
hiding of methods mentioned.
 
I can't give you a good explanation of that. Especially because you can
"overwrite" a method even if it is not declared virtual in the base class
(by declaring a method with the same name an params in the child with "new")
and having the same behaviour. Probably the binding mechanisms take some
advantages of it, but it is just a supposition, I didn't explore this issue.
Another questions is "why not?". Anyhow I find it good as long as the code
is more readable and understandable, when you see the "override" keyword in
a method decalaration it is clear that it overrides/implements a method of a
base class.

Where?
1. In polymorphic structures, where the base class contains some common
behaviour/property that is the same for the derrived classes i.e.:
- shape (base) with circle, square, triangle (derrived): a setColor() method
is the same for all the shapes
2. In classes that contains general behaviours, when you want the derrived
classes only to extend the behaviours and not to change any of the base
behaviours i.e.:
- humanBeing (base) that contains goToSleep(), awake(), walk(), jump(),
stay(); women derrived from humanBeing that contains talkTooMuch(),
spendMensIncome() and man that contains watchAllSportAtTV(),
seekOtherWomen() and so on... :))

Anyhow you can do that explicitly by marking the methods as "sealed", and ,
as I already wrote, you can trick that.

--
Horatiu Ripa
Software Development Manager
Business Logic Systems LTD
21 Victor Babes str., 1st floor, 3400 Cluj-Napoca, Romania
Phone/Fax: +40 264 590703
Web: www.businesslogic.co.uk

This email (email message and any attachments) is strictly confidential,
possibly privileged and is intended solely for the person or organization to
whom it is addressed. If you are not the intended recipient, you must not
copy, distribute or take any action in reliance on it. If you have received
this email in error, please inform the sender immediately before deleting
it. Business Logic Systems Ltd accepts no responsibility for any advice,
opinion, conclusion or other information contained in this email or arising
from its disclosure.
 
Jon Skeet said:
And that, as far as I'm concerned, is the principal feature of being
non-virtual.

No - the principal feature of being non-virtual, is that non-virtual methods
are resolved at compile-time (a.k.a. static or early binding), so a call
*always* executes the same implementation.
No, it has no concept of instance methods hiding other instance
methods, which I view as being separate from having no concept of non-
virtual methods.

Think again. *Only* non-virtual methods can be "hidden".
In my view, they can be sealed to prevent them being virtual any
further.

"...virtual any further" = "...overriden any further"
My way of looking at things is that something is virtual if it can be
overridden, and is non-virtual if it can't.

It's all a matter of definition, of course, but mine seems to fit in
pretty well with this section from the MSDN on virtual members:

<quote>
The virtual keyword is used to modify a method or property declaration,
in which case the method or the property is called a virtual member.
The implementation of a virtual member can be changed by an overriding
member in a derived class.

When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member. (For more information on run-
time type and most derived implementation, see 10.5.3 Virtual methods.)

By default, methods are non-virtual. You cannot override a non-virtual
method.
</quote>

OK - but you can still hide it.
Here's another one, from the C# language specification:

<quote>
The implementation of a non-virtual method is invariant: The
implementation is the same whether the method is invoked on an instance
of the class in which it is declared or an instance of a derived class.
In contrast, the implementation of a virtual method can be superseded
by derived classes.
</quote>

A final method in Java absolutely satisfies the descriptions of non-
virtual methods above. Note that in neither of those two quotes is
hiding of methods mentioned.

A final method in Java absolutely does *not* satisfy the descriptions of
non-virtual methods above - simply because you cannot hide it as you can in
C#. Moreover, even a C# "sealed" method which is the most close to a Java
"final" method, can be hidden by further subclasses

There are two separate notions:
1) Overriding - by overriding, a subclass replaces method pointers in
object's v-table and since all method invokations are made through that
v-table, you will always get the overriding implementation no matter from
which site you call it (either from superclass' site or from subclass'
site) - hence, dynamic binding. Also, that's the reason for naming those
methods "virtual" - because their implementation is not known until
run-time.
2) Hidding - this is a totally different mechanism: method invokations are
resolved during compile-time (static binding); so, there is no v-table to go
through - the call is direct.

In summary: when you call a non-virtual method, you will _always_ get the
same implementation executed; when you call a virtual method, you will *not*
always get the same implementation executed - it depends on the overriding
subclasses.

//++ run this test ++++++

using System;

class A {
public void M1() {
Console.WriteLine("A::M1");
}

virtual public void M2() {
Console.WriteLine("A::M2");
}
}

class B : A {
new public void M1() {
Console.WriteLine("B::M1 - I'm hidding A::M1");
}

// only virtual methods can be sealed
sealed override public void M2() {
Console.WriteLine("B::M2 - I'm overriding A::M2");
}
}

class C : B {
new public void M1() {
Console.WriteLine("C::M1 - I'm hidding B::M1");
}

// still can hide (virtually!) the sealed base
new virtual public void M2() {
Console.WriteLine("C::M2 - I'm hidding B::M2, since it is sealed");
}
}

class TestDerivation {
static void Main() {
A objA;

objA = new A();
objA.M1();
objA.M2();

objA = new B();
objA.M1(); // non-virtual - A::M1 implementation will execute
objA.M2(); // virtual - B::M2 implementation will execute

objA = new C();
objA.M1(); // non-virtual - A::M1 implementation will execute
objA.M2(); // virtual and sealed at B class level
// - B::M2 implementation will execute
}
}
 
Hi,
And that, as far as I'm concerned, is the principal feature of being
non-virtual.
I don't know how is in JAVA, but if you assert here that declaring a method
as *sealed* si the same as declaring non-virtual method you are wrong. Such
a method is still virtulal.

class A
{
public virtual void f()
{
}
}

class B: A
{
public override void f()
{
}
}

class C: B
{
public override sealed void f();
{
}
}

A a = new C()
a.f() calls C.f()
Isn't it virtual? If it wasn't it would call A.f()
*sealed* modifier force you to stop using overriden until you don't use
*virtual* again and then you can continue override the method. BTW the
compiler generates *callvirt* instruction as a evidence of that the method
is indeed *virtual*

In my view, they can be sealed to prevent them being virtual any
further.

In c# you can keep going with overrideing the method which was sealed. what
you have to is to declared it as virtual again(to start new virtual
implemetation).

That is posible because when CLR decides, which is most-derived method it
doesn't take into account only the runtime type of the object it kind of
takes into account the type of the variable as well.
To be more strict
callvirt is provided with the name of the class from where to start looking
for the most-derived implementation.
My way of looking at things is that something is virtual if it can be
overridden, and is non-virtual if it can't.

When you put *sealed* modifier for a method you have to put override as well
(other wise it does'n make sence to prohibit overriding of something which
cannot be overrided anyway). The modifier *override* already means that the
method is virtual.
It's all a matter of definition, of course, but mine seems to fit in
pretty well with this section from the MSDN on virtual members:

<quote>
The virtual keyword is used to modify a method or property declaration,
in which case the method or the property is called a virtual member.
The implementation of a virtual member can be changed by an overriding
member in a derived class.

When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member. (For more information on run-
time type and most derived implementation, see 10.5.3 Virtual methods.)

By default, methods are non-virtual. You cannot override a non-virtual
method.
</quote>

If you read further down the same section you will find example of hiding
virtual methods, which is more closely to what happend when you declare a
method as a *sealed*. *sealed* modifier just force you to hide the method if
you want to change the implementation.


Here's another one, from the C# language specification:

<quote>
The implementation of a non-virtual method is invariant: The
implementation is the same whether the method is invoked on an instance
of the class in which it is declared or an instance of a derived class.
In contrast, the implementation of a virtual method can be superseded
by derived classes.
</quote>

A final method in Java absolutely satisfies the descriptions of non-
virtual methods above. Note that in neither of those two quotes is
hiding of methods mentioned.

If *final* in JAVA means that the method cannod be overriden or hid then it
is different form the non-virtual methods.
Non-virtual methods cannot be overriden - OK. One can hide then, though.

So my question is: Why C# allows virtual methods to be hidden. Isn't it
error prone.
I believe that the best is:
1. To have virtual and non-virtual methods.
2. Sealing virtual methods has to prevent further overriding and hiding the
methods.

And actually I think I know the answer. It is side efect of the way the CLR
resolves wich is the most-derived method. .NET is cross langage platform and
if C# was preventing this using calsses written in other languges (allowing
hiding virtual methods) would put C# programmers to consfusion.

B\rgds
100
 
Hi,
And that, as far as I'm concerned, is the principal feature of being
non-virtual.
I don't know how is in JAVA, but if you assert here that declaring a method
as *sealed* si the same as declaring non-virtual method you are wrong. Such
a method is still virtulal.

class A
{
public virtual void f()
{
}
}

class B: A
{
public override void f()
{
}
}

class C: B
{
public override sealed void f();
{
}
}

A a = new C()
a.f() calls C.f()
Isn't it virtual? If it wasn't it would call A.f()
*sealed* modifier force you to stop using overriden until you don't use
*virtual* again and then you can continue override the method. BTW the
compiler generates *callvirt* instruction as a evidence of that the method
is indeed *virtual*

In my view, they can be sealed to prevent them being virtual any
further.

In c# you can keep going with overrideing the method which was sealed. what
you have to is to declared it as virtual again(to start new virtual
implemetation).

That is posible because when CLR decides, which is most-derived method it
doesn't take into account only the runtime type of the object it kind of
takes into account the type of the variable as well.
To be more strict
callvirt is provided with the name of the class from where to start looking
for the most-derived implementation.
My way of looking at things is that something is virtual if it can be
overridden, and is non-virtual if it can't.

When you put *sealed* modifier for a method you have to put override as well
(other wise it does'n make sence to prohibit overriding of something which
cannot be overrided anyway). The modifier *override* already means that the
method is virtual.
It's all a matter of definition, of course, but mine seems to fit in
pretty well with this section from the MSDN on virtual members:

<quote>
The virtual keyword is used to modify a method or property declaration,
in which case the method or the property is called a virtual member.
The implementation of a virtual member can be changed by an overriding
member in a derived class.

When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member. (For more information on run-
time type and most derived implementation, see 10.5.3 Virtual methods.)

By default, methods are non-virtual. You cannot override a non-virtual
method.
</quote>

If you read further down the same section you will find example of hiding
virtual methods, which is more closely to what happend when you declare a
method as a *sealed*. *sealed* modifier just force you to hide the method if
you want to change the implementation.


Here's another one, from the C# language specification:

<quote>
The implementation of a non-virtual method is invariant: The
implementation is the same whether the method is invoked on an instance
of the class in which it is declared or an instance of a derived class.
In contrast, the implementation of a virtual method can be superseded
by derived classes.
</quote>

A final method in Java absolutely satisfies the descriptions of non-
virtual methods above. Note that in neither of those two quotes is
hiding of methods mentioned.

If *final* in JAVA means that the method cannod be overriden or hid then it
is different form the non-virtual methods.
Non-virtual methods cannot be overriden - OK. One can hide then, though.

So my question is: Why C# allows virtual methods to be hidden. Isn't it
error prone.
I believe that the best is:
1. To have virtual and non-virtual methods.
2. Sealing virtual methods has to prevent further overriding and hiding the
methods.

And actually I think I know the answer. It is side efect of the way the CLR
resolves wich is the most-derived method. .NET is cross langage platform and
if C# was preventing this using calsses written in other languges (allowing
hiding virtual methods) would put C# programmers to consfusion.

B\rgds
100
 
Horatiu Ripa said:
I can't give you a good explanation of that. Especially because you can
"overwrite" a method even if it is not declared virtual in the base class
(by declaring a method with the same name an params in the child with "new")
and having the same behaviour. Probably the binding mechanisms take some
advantages of it, but it is just a supposition, I didn't explore this issue.
Another questions is "why not?". Anyhow I find it good as long as the code
is more readable and understandable, when you see the "override" keyword in
a method decalaration it is clear that it overrides/implements a method of a
base class.

I've already explained what's the difference between "overriding" and
"hidding",
and it is not superficial.
Where?
1. In polymorphic structures, where the base class contains some common
behaviour/property that is the same for the derrived classes i.e.:
- shape (base) with circle, square, triangle (derrived): a setColor() method
is the same for all the shapes

OK - some "setColor(int32)" method is implemented the same across the
derivation tree.
So what? What advantage I'm gaining by implementing this method as
non-virtual?
The only advantage I can see, is some increased performance (because the
call goes
direcly to the method implementation and not through a v-table).
And by the way, a typical implementation of "setColor(int32)" will probably
look like:
this.color = iColor; hardly an algorithm, so it couldn't be expected to
change much
across the derivation tree anyway.
2. In classes that contains general behaviours, when you want the derrived
classes only to extend the behaviours and not to change any of the base
behaviours i.e.:
- humanBeing (base) that contains goToSleep(), awake(), walk(), jump(),
stay(); women derrived from humanBeing that contains talkTooMuch(),
spendMensIncome() and man that contains watchAllSportAtTV(),
seekOtherWomen() and so on... :))

I'm not sure about this example as well. A human being does "goToSleep()",
but
men and women can do it differently - a men will go to sleep without
brushing his teeth.
Anyhow you can do that explicitly by marking the methods as "sealed", and ,
as I already wrote, you can trick that.

As I've already said, "sealed" methods can still be hidden (unlike Java's
"final") -
so a "sealed" method is just a non-virtual method.
 
Adrian Herscu said:
No - the principal feature of being non-virtual, is that non-virtual methods
are resolved at compile-time (a.k.a. static or early binding), so a call
*always* executes the same implementation.

And that's exactly what a method not being overridable gives you.
Think again. *Only* non-virtual methods can be "hidden".

Not sure where you get that from:

using System;

class Base
{
public virtual void Foo()
{
Console.WriteLine ("Base.Foo");
}
}

class Derived : Base
{
public new void Foo()
{
Console.WriteLine ("Derived.Foo");
}
}

public class Test
{
static void Main()
{
Base b = new Derived();
Derived d = new Derived();

b.Foo();
d.Foo();
}
}

Base.Foo is clearly a virtual method, but as far as I can see
Derived.Foo hides it in exactly the same way as if it were non-virtual.
Take away the keyword "new" and you get a warning:

<quote>
Test.cs(13,17): warning CS0114: 'Derived.Foo()' hides inherited member
'Base.Foo()'. To make the current member override that implementation,
add the override keyword. Otherwise add the new keyword.
"...virtual any further" = "...overriden any further"
Yes.


OK - but you can still hide it.

Yes, and what's your point? You can hide a non-virtual method in C#.
You can't in Java. That doesn't stop it from being non-virtual.
A final method in Java absolutely does *not* satisfy the descriptions of
non-virtual methods above - simply because you cannot hide it as you can in
C#.

Where in that quote does it say that you have to be able to hide a
method in order for it not to be virtual?
Moreover, even a C# "sealed" method which is the most close to a Java
"final" method, can be hidden by further subclasses

Yes, but as I've said, I see hiding as separate notions. You seem to as
well below:
There are two separate notions:
1) Overriding - by overriding, a subclass replaces method pointers in
object's v-table and since all method invokations are made through that
v-table, you will always get the overriding implementation no matter from
which site you call it (either from superclass' site or from subclass'
site) - hence, dynamic binding. Also, that's the reason for naming those
methods "virtual" - because their implementation is not known until
run-time.
2) Hidding - this is a totally different mechanism: method invokations are
resolved during compile-time (static binding); so, there is no v-table to go
through - the call is direct.

Well, unless the new method is also virtual, of course, in which case
you still need a v-table. (If you add an extra class D to your example
which extends D and overrides M2, then do

C x = new D();
C.M2();

then D.M2 will get executed.
In summary: when you call a non-virtual method, you will _always_ get the
same implementation executed; when you call a virtual method, you will *not*
always get the same implementation executed - it depends on the overriding
subclasses.

And what part of that summary (which doesn't mention hiding, note)
doesn't apply to final methods in Java?
//++ run this test ++++++

Why? What do you think it shows? I know what is called... I don't see
why you think that the test shows that Java doesn't have non-virtual
methods.
 
I don't know how is in JAVA, but if you assert here that declaring a method
as *sealed* si the same as declaring non-virtual method you are wrong. Such
a method is still virtulal.

No it's not.

A a = new C()
a.f() calls C.f()
Isn't it virtual?

A.f is virtual,but C.f isn't, because you can't override it in a class
that derives from C.
If it wasn't it would call A.f()

Nope. From the C# specification again:

<quote>
The implementation of a virtual member can be changed by an overriding
member in a derived class.
</quote>

Now, can you override f() in a class derived directly from C? No? Then
it's not virtual.
*sealed* modifier force you to stop using overriden until you don't use
*virtual* again and then you can continue override the method.

You can never override the actual sealed method. You can hide it with
another virtual method and then override *that*, but that's not
actually overriding the sealed (non-virtual) method.
BTW the
compiler generates *callvirt* instruction as a evidence of that the method
is indeed *virtual*

That's evidence of A.f() being virtual, not evidence of C.f() being
virtual.
In c# you can keep going with overrideing the method which was sealed.

No you can't.
what
you have to is to declared it as virtual again(to start new virtual
implemetation).

You also have to declare it as "new" and *hide* the previous method.
That's *not* overriding it.
That is posible because when CLR decides, which is most-derived method it
doesn't take into account only the runtime type of the object it kind of
takes into account the type of the variable as well.

The CLR doesn't take that into account; the compiler does.
To be more strict
callvirt is provided with the name of the class from where to start looking
for the most-derived implementation.

Yes, but it will stop when it gets to a sealed method. In other words,
there's no way that you can write a class MyDerivedClass such that

C c = new MyDerivedClass();
c.f();

will call anything other than c.f();

(assuming you don't change C itself).

If you think you can, please demonstrate it.
When you put *sealed* modifier for a method you have to put override as well
(other wise it does'n make sence to prohibit overriding of something which
cannot be overrided anyway).

Indeed, but that's irrelevant.
The modifier *override* already means that the method is virtual.

No, it means the method in the class it's deriving from is virtual.

If you read further down the same section you will find example of hiding
virtual methods, which is more closely to what happend when you declare a
method as a *sealed*. *sealed* modifier just force you to hide the method if
you want to change the implementation.

That doesn't change the implementation though - it just provides a new
method. It doesn't change the implementation in the same way that
overriding does.
If *final* in JAVA means that the method cannod be overriden or hid then it
is different form the non-virtual methods.

It's different from C# due to the fact that you can't hide it, but that
doesn't mean it's non-virtual. You can't hide it just because you can't
hide methods at all in Java. If we were to apply your logic above, we'd
also come to the conclusion that there aren't any virtual methods in
Java either, as they can't be hidden. Do you really believe that every
method in Java is neither virtual nor non-virtual?
Non-virtual methods cannot be overriden - OK. One can hide then, though.

You don't *have* to be able to hide them in order for them to be non-
virtual though! Hiding's just a different concept in the same area.
So my question is: Why C# allows virtual methods to be hidden. Isn't it
error prone.

Not really, because there's a warning message if you try to do it.
I believe that the best is:
1. To have virtual and non-virtual methods.

Which both C# and Java have.
2. Sealing virtual methods has to prevent further overriding and hiding the
methods.

I disagree with this - a warning is all that's required to avoid
hiding. Sealing an otherwise virtual method makes it non-virtual, and
that's all that's required.
And actually I think I know the answer. It is side efect of the way the CLR
resolves wich is the most-derived method. .NET is cross langage platform and
if C# was preventing this using calsses written in other languges (allowing
hiding virtual methods) would put C# programmers to consfusion.

I don't think that was the reason at all. I think it was to prevent
classes from breaking when they're recompiled against newer versions of
libraries they may use. You get a warning if you try to hide a member
(because the member may not have existed before), but you get the same
behaviour, and can remove the warning by explicitly saying that that's
what you wanted to do. Don't forget that this method may itself be part
of a public API which can't easily be changed.
 
Jon Skeet said:
And that, as far as I'm concerned, is the principal feature of being
non-virtual.

In fact, in C# a non-virtual method which implements an interface method is
actually compiled into a "virtual sealed" method. The only way to tell this
is with ILDASM, since it acts exactly like a non-virtual method.
 
Eric Gunnerson said:

Shame Anders has a pretty dodgy section in that article:

<quote>
Anders Hejlsberg: There are several reasons. One is performance. We can
observe that as people write code in Java, they forget to mark their
methods final. Therefore, those methods are virtual. Because they're
virtual, they don't perform as well. There's just performance overhead
associated with being a virtual method. That's one issue.
</quote>

In modern Java VMs (or at least HotSpot), methods are actually treated
as non-virtual until they are overridden, whereupon code which calls
the overridden method is rejitted to make a virtual call. Of course,
this trickery may well have been included only because so many methods
in Java *are* virtual, but I still think it's important to note.

(I agree with the rest of the article though :)
 
Back
Top