Should I mark all methods virtual?
In C# you have to mark method as virtual to make it possible to override. Does it mean that in C# you should mark all methods virtual (except a few ones that you don't want to be overridden), since most likely you don't know in what way your class can be inherited?
No. If the language designers thought that virtual should have been the default then it would have been the default.
Overridablility is a feature, and like all features it has costs. The costs of an overrideable method are considerable: there are big design, implementation and testing costs, particularly if there is any "sensitivity" to the class; virtual methods are ways of introducing untested third-party code into a system and that has a security impact.
If you don't know how you intend your class to be inherited then don't publish your class because you haven't finished designing it yet. Your extensibility model is definitely something you should know ahead of time; it should deeply influence your design and testing strategy.
I advocate that all classes be sealed and all methods be non-virtual until you have a real-world customer-focussed reason to unseal or to make a method virtual.
Basically your question is "I am ignorant of how my customers intend to consume my class; should I therefore make it arbitrarily extensible?" No; you should become knowledgable! You wouldn't ask "I don't know how my customers are going to use my class, so should I make all my properties read-write? And should I make all my methods read-write properties of delegate type so that my users can replace any method with their own implementation?" No, don't do any of those things until you have evidence that a user actually needs that capability! Spend your valuable time designing, testing and implementing features that users actually want and need, and do so from a position of knowledge.
No! Because you don't know how your class will be inherited, you should only mark a method as virtual
if you know that you want it to be overridden.
No. Only methods that you want derived classes to specify should be virtual.
Virtual is not related to final.
To prevent overriding of a virtual method in c# you use sealed
public class MyClass
{
public sealed override void MyFinalMethod() {...}
}
In my opinion the currently accepted answer is unnecessarily dogmatic.
Fact is that when you don't mark a method as virtual
, others cannot override its behaviour and when you mark a class as sealed
others cannot inherit from the class. This can cause substantial pain. I don't know how many times I cursed an API for marking classes sealed
or not marking methods virtual
simply because they did not anticipate my use case.
Theoretically it might be the correct approach to only allow overriding methods and inheriting classes which are meant to be overridden and inherited but in practice it's impossible to foresee every possible scenario and there really isn't a good reason to be so closed in.
- If you don't have a very good reason then don't mark classes as
sealed
. - If your library is meant to be consumed by others, then at least try to mark the main methods of a class which contain the behaviour as
virtual
.
One way to make the call is to look at the name of the method or property. A GetLength() method on a List does exactly what the name implies and it doesn't allow for much of interpretation. Changing its implementation would likely be not very transparent so marking it as virtual
is probably unnecessary. Marking the Add
method as virtual is far more useful as someone could create a special List which only accepts some objects via the Add method etc. Another example are custom controls. You would want to make the main drawing method virtual
so others can use the bulk of the behaviour and just change the look but you probably wouldn't override the X and Y properties.
In the end you often don't have to make that decision right away. In an internal project where you can easily change the code anyway I wouldn't worry about these things. If a method needs to be overridden you can always make it virtual when this happens. On the contrary, if the project is an API or library which is consumed by others and slow to update, it certainly pays off to think about which classes and methods might be useful. In this case I think it's better to be open rather than strictly closed.