views:

1765

answers:

11

Unlike Java, why C# treats methods as non-virtual functions by default? Is it more likely to be a performance issue rather than other possible outcomes?

I remind reading a paragraph from Anders Hejlsberg about the several advantages the existing architecture is bringing out. But, what about side effects? Is it really a good trade-off to have non-virtual methods by default?

+6  A: 

C# is influenced by C++ (and more). C++ does not enable dynamic dispatch (virtual functions) by default. One (good?) argument for this is the question: "How often do you implement classes that are members of a class hiearchy?". Another reason to avoid enabling dynamic dispatch by default is the memory footprint. A class without a virtual pointer (vpointer) pointing to a virtual table, is ofcourse smaller than the corresponding class with late binding enabled.

The performance issue is not so easy to say "yes" or "no" to. The reason for this is the Just In Time (JIT) compilation which is a run time optimization in C#.

Another, similar question about "speed of virtual calls.."

Schildmeijer
I am a bit doubtful that virtual methods have performance implications for C#, because of the JIT compiler. That's one of the area where JIT can be better than offline compilation, because they can inline function calls which are "unknown" before runtime
David Cournapeau
I agree with your point of view Roger! +1
Geo
Actually, I think it's more influenced by Java than C++ which does that by default.
Mehrdad Afshari
+42  A: 

Classes should be designed for inheritance to be able to take advantage of it. Having methods virtual by default means that every function in the class can be plugged out and replaced by another, which is not really a good thing. Many people even believe that classes should have been sealed by default.

virtual methods can also have a slight performance implication. This is not likely to be the primary reason, however.

Mehrdad Afshari
Personally, I doubt that part about performance. Even for virtual functions, the compiler is very able to figure out where to replace `callvirt` by a simple `call` in the IL code (or even further downstream when JITting). Java HotSpot does the same. The rest of the answer is spot-on.
Konrad Rudolph
I agree performance is not at the forefront, but it *can* have performance implications too. It's probably very small. Certainly, it's not *the reason* for this choice, however. Just wanted to mention that.
Mehrdad Afshari
Sealed classes make me want to punch babies.
mxmissile
@mxmissile: me too, but good API design is hard anyway. I think sealed-by-default makes perfect sense for code you own. More often than not, the other programmer on your team _did not_ consider inheritance when they implemented that class you need, and sealed-by-default would convey that message quite well.
romkyns
I think there is a large performance consideration here: virtual methods cannot be inlined unless you do a lot of fancy stuff to determine the actual runtime type profiles of the code. Hotspot specializes in just this sort of thing which is why it starts out by interpreting the code before using the information it gathers to compile it. A basic tenet of good API design is to program to interfaces rather than implementation classes which will always require virtual calls through the interface anyway.
Ramon
+7  A: 

Because it's too easy to forget that a method may be overridden and not design for that. C# makes you think before you make it virtual. I think this is a great design decision. Some people (such as Jon Skeet) have even said that classes should be sealed by default.

Zifre
+5  A: 

To summarize what others said, there are a few reasons:

1- In C#, there are many things in syntax and semantics that come straight from C++. The fact that methods where not-virtual by default in C++ influenced C#.

2- Having every method virtual by default is a performance concern because every method call must use the object's Virtual Table. Moreover, this strongly limits the Just-In-Time compiler's ability to inline methods and perform other kinds of optimization.

3- Most importantly, if methods are not virtual by default, you can guarantee the behavior of your classes. When they are virtual by default, such as in Java, you can't even guarantee that a simple getter method will do as intended because it could be overridden to do anything in a derived class (of course you can, and should, make the method and/or the class final).

One might wonder, as Zifre mentioned, why the C# language did not go a step further and make classes sealed by default. That's part of the whole debate about the problems of implementation inheritance, which is a very interesting topic.

Trillian
+2  A: 

The simple reason is design and maintenance cost in addition to performance costs. A virtual method has additional cost as compared with a non-virtual method because the designer of the class must plan for what happens when the method is overridden by another class. This has a big impact if you expect a particular method to update internal state or have a particular behavior. You now have to plan for what happens when a derived class changes that behavior. It's much harder to write reliable code in that situation.

With a non-virtual method you have total control. Anything that goes wrong is the fault of the original author. The code is much easier to reason about.

JaredPar
A: 

It is certainly not a performance issue. Sun's Java interpreter uses he same code to dispatch (invokevirtual bytecode) and HotSpot generates exactly the same code whether final or not. I believe all C# objects (but not structs) have virtual methods, so you are always going to need the vtbl/runtime class identification. C# is a dialect of "Java-like languages". To suggest it comes from C++ is not entirely honest.

There is an idea that you should "design for inheritance or else prohibit it". Which sounds like a great idea right up to the moment you have a severe business case to put in a quick fix. Perhaps inheriting from code that you don't control.

Tom Hawtin - tackline
A: 

One should not forget about extension methods in C# 3.0 in this discussion.

{Working hard on refraining from re-telling of the Knock-knock joke with Java on the other side of the door.}

GregC
A: 

It seems we have the choice of a C++ like situation, where we have to declare a method virtual every time we want to over ride it, or a java/C# like situation, where whenever we don't want to override a method and want to be more efficient, we have to declare the method final. The java class libraries declare tons of methods final, just because having them virtual results in a loss of efficiency.

CrazyJugglerDrummer
A: 

If all C# methods were virtual then the vtbl would be much bigger.

C# objects only have virtual methods if the class has virtual methods defined. It is true that all objects have type information that includes a vtbl equivalent, but if no virtual methods are defined then only the base Object methods will be present.

@Tom Hawtin: It is probably more accurate to say that C++, C# and Java are all from the C family of languages :)

Thomas Bratt
+3  A: 

I'm surprised that there seems to be such a consensus here that non-virtual-by-default is the right way to do things. I'm going to come down on the other - I think pragmatic - side of the fence.

Most of the justifications read to me like the old "If we give you the power you might hurt yourself" argument. From programmers?!

It seems to me like the coder who didn't know enough (or have enough time) to design their library for inheritance and/or extensibility is the coder who's produced exactly the library I'm likely to have to fix or tweak - exactly the library where the ability to override would come in most useful.

The number of times I've had to write ugly, desperate work-around code (or to abandon usage and roll my own alternative solution) because I can't override far, far outweighs the number of times I've ever been bitten (e.g. in Java) by overriding where the designer might not have considered I might.

Non-virtual-by-default makes my life harder.

mwardm
A: 

Coming from a perl background I think C# messed up by sealing the doom of every developer who might want to modify the behaviour of a base class' non virtual method without forcing all users of the new class to be aware of potentially behind the scene details.

Consider the List classes Add method. What if a developer wants to update one of several potential databases whenever a List is 'Added' to? If 'Add' had been virtual by default the developer could develop a 'BackedList' class that overloaded the 'Add' method without forcing all client code to know it was a 'BackedList' instead of a regular 'List'. For all practical purposes the 'BackedList' can be viewed as just another 'List'.

Travis