Should I mark all methods virtual?

C#JavaMethodsVirtual Functions

C# Problem Overview


In Java you can mark method as final to make it impossible to override.

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?

C# Solutions


Solution 1 - C#

> 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.

Solution 2 - C#

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.

  1. If you don't have a very good reason then don't mark classes as sealed.
  2. 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.

Solution 3 - C#

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.

Solution 4 - C#

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() {...}
}

Solution 5 - C#

We can conjure up reasons for/again either camp, but that's entirely useless.

In Java there are millions of unintended non-final public methods, but we hear very few horror stories.

In C# there are millions of sealed public methods, and we hear very few horror stories.

So it is not a big deal - the need to override a public method is rare, so it's moot either way.


This reminds me of another argument - whether a local variable should be final by default. It is a pretty good idea, but we cannot exaggerate how valuable it is. There are billions of local variables that could be, but are not, final, but it has been shown to be an actual problem.

Solution 6 - C#

Yes you should. I wish to answer a different answer than most other answers. This is a flaw in C#. A defect. A mistake in its design. You can see that when comparing to Java where all methods are "virtual" unless, specified otherwise ("final"). Of course that if there is a class "Rectangle" with a method of "Area", and you wish to have your own class that represents a "Rectangle" with margins. You wish to take advantage of the existing class with all of its properties and methods and you just want to add a property of "margin" that adds some value to the regular rectangle area, and if the area method in Rectangle is not marked virtual, you are doomed. Image please a method that takes an array of Rectangles and returns the sum of the area of all rectangles. Some can be regular rectangles and some with margin. Now read back the answer that is marked "correct" the describe "secuirty issue" or "testing". Those are meaningless compared to the disability to override.

I am not surprised that others answered "no". I am surprised that the authors of C# couldn't see that while basing their language on Java.

Solution 7 - C#

Making a method virtual will generally slow down any code that needs to call it. This slowdown will be insignificant but may in some cases be quite large (among other things, because non-virtual method calls may be in-lined, which may in turn allow the optimizer to eliminate unnecessary operations). It's not always possible to predict the extent to which virtual calls may affect execution speed, and one should generally void doing things which will make code slower except when there's a discernible benefit for doing so.

The performance benefit of making methods non-virtual is probably sufficient in many cases to justify having methods be non-virtual by default, but when classes are designed to be inherited most methods should be virtual and unsealed; the primary usage for non-virtual or sealed methods should be as wrappers for other (possibly protected) virtual methods (code that wants to change the underlying behavior should override the appropriate virtual rather than the wrapper).

There are frequently non-performance-related reasons for marking classes as sealed or limiting inheritance to other classes within the assembly. Among other things, if a class is externally inheritable, all members with protected scope are effectively added to its public API, and any changes to their behavior in the base class may break any derived classes that rely upon that behavior. On the other hand, if a class is inheritable, making its methods virtual doesn't really increase its exposure. If anything, it may reduce derived class's reliance upon the base class internals by allowing them to completely "bury" aspects of the base class implementation that are no longer relevant in the derived class [e.g. if the members of List<T> were virtual, a derived class which overrode them all could use an array of arrays to hold things (avoiding large-object-heap issues), and wouldn't have to try to keep the private array used by List<T> consistent with the array-of-arrays.

Solution 8 - C#

No, you should not mark all methods as virtual. You should consider how your class could be inherited. If the class should not be inherited, then mark it sealed and obviously the members should not be virtual. If your class is likely to be inherited, you really should maximize the ability to override the behavior. Therefore generously use virtual everywhere in such classes unless you have a reason not to.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorgii OleinikovView Question on Stackoverflow
Solution 1 - C#Eric LippertView Answer on Stackoverflow
Solution 2 - C#Patrick KlugView Answer on Stackoverflow
Solution 3 - C#John SaundersView Answer on Stackoverflow
Solution 4 - C#nunespascalView Answer on Stackoverflow
Solution 5 - C#irreputableView Answer on Stackoverflow
Solution 6 - C#Elad LaviView Answer on Stackoverflow
Solution 7 - C#supercatView Answer on Stackoverflow
Solution 8 - C#Elliott AndersonView Answer on Stackoverflow