开发者

Why methods in C# are not automatically virtual? [duplicate]

This question already has answers here: Closed 12 years ago.

Possible Duplicate:

Why C# implements methods as non-virtual by default?

It would be much more less work to define which methods are NOT overideable instead of which are overideable because (at least for me), when you're designing a class, you don't care if its heirs will override your methods or not...

So, why methods in C# are not automatically virtual? What is the common sense in t开发者_如何学运维his?


Anders Hejlsberg answered that question in this interview and I quote:

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.

A more important issue is versioning. There are two schools of thought about virtual methods. The academic school of thought says, "Everything should be virtual, because I might want to override it someday." The pragmatic school of thought, which comes from building real applications that run in the real world, says, "We've got to be real careful about what we make virtual."

When we make something virtual in a platform, we're making an awful lot of promises about how it evolves in the future. For a non-virtual method, we promise that when you call this method, x and y will happen. When we publish a virtual method in an API, we not only promise that when you call this method, x and y will happen. We also promise that when you override this method, we will call it in this particular sequence with regard to these other ones and the state will be in this and that invariant.

Every time you say virtual in an API, you are creating a call back hook. As an OS or API framework designer, you've got to be real careful about that. You don't want users overriding and hooking at any arbitrary point in an API, because you cannot necessarily make those promises. And people may not fully understand the promises they are making when they make something virtual.


You should care which members can be overridden in derived classes.

Deciding which methods to make virtual should be a deliberate, well-thought-out decision - not something that happens automatically - the same as any other decisions regarding the public surface of your API.


Beyond the design and clarity reasons a non-virtual method is also technically better for a couple of reasons:

  • Virtual methods take longer to call (because the runtime needs to navigate through the virtual lookup table to find the actual method to call)
  • Virtual methods can't be inlined (because the compiler doesn't know at compile time which method will eventually be called)

Therefore unless you have specific intentions to override the method it is better for it to be non-virtual.


Convention? Nothing more, I would think. I know Java automatically makes methods virtual, while C# does not, so there's clearly some disagreement at some level as to what's better. Personally, I prefer the C# default - consider that overriding methods is a lot less common than not overriding them, so it would seem more concise to define virtual methods explicitly.


See also the answer of Anders Hejlsberg (the inventor of C#) at A Conversation with Anders Hejlsberg, Part IV.


To paraphrase Eric Lippert, one of the guys who designed C#: So you code doesn't get accidentally broken when the source code you recieved from a third party is changed. In other words, to prevent the Brittle Base Class problem.

If a method is to be virtual, if because you (supposedly) made the conscious decision to allow the function to be replaceable, and designed, tested and document around that. What happens if, say, you made a function "frob" and, in some subsequent version, the base class's makers decide to also make a function "frob"?


So it's clear whether you're allowing overriding or a method or forcing hiding of a method (via the new keyword).

Forcing you to add the keyword removes any ambiguity that might be there.


There are always two approaches when you want to specify that you are allowing or denying something. You can either trust everyone and punish sinners or you can distrust everyone and force them to ask permission.

There are some minor performance problems with virtual methods - can't be inlined, slower to call than non-virtual methods - but that really isn't that important.

More significantly they pose threat for your design. It's not about caring what others will do with your class it's about good object design. When a method is virtual you are saying that you can plug it out and replace it with different implementation. As I say you must treat such a method as an enemy - you can't trust it. You can't rely on any side-effects. You have to set up very strict contract for that method and stick with it.

If you consider that human is very lazy and forgetting creature which approach is more prudent?

I have never personally used virtual method in my design. If there is some logic that my class uses and I want it to be interchangeable then I just create interface for it. That interface than constitutes above mentioned contract. There are some situations where you really need virtual methods but I think that those are quite rare.


I believe there is an efficiency issue as well as the reasons others have posted. There is no need to spend the cpu cycles to look for an override if the method is not virtual.


When someone inherits from your class, that would give them the ability to change how any method works when the base class uses it. If you have a method that you absolutely need it to perform an action a certain way in the base class, you would have no way not allowing someone to change that functionality.

Here's one example. Suppose you have a function that you expect to not return an error. Someone comes in and decides to change it so that on Tuesday, it throws an out of range exception. Now the code in the base class fails, because something it depended on happening changed.


Because it's not Java

Seriously, just a different backing philosophy. Java wanted wanted extensibility to be the default and encapsulation to be explicit and C# wanted extensibility to be explicit and encapsulation to be the default.


Actually, that's bad design practice. Not caring which methods are override-able and which are not, I mean. You should always think about what should and should be override-able just as you should carefully consider what should or shouldn't be public!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜