There are 2 major reasons why virtual by default is so much better than non-virtual.
- The main principles about usefulness of OOP is Liskov substitution principle, polymorphism and late binding . I use strategy pattern all the time and for that I want my methods to be virtual. If you are fan of Open/closed principle you should like Java philosophy more. You should be able to change behavior without changing your source code. You can do that with dependency injection and virtual methods.
- If you call a non-virtual method then you want to know from your code which class method you are calling. The flaw of .net is that you cannot know that from your code.
- Another benefit of virtual-only method is that it is much easier to test your code because you can make Mocks of your (or 3rd party) classes. Testing with Mockito is really easy in Java.
Example
In Java if you define ClassB as
public class ClassB extends ClassA {
@Override
public void run() {
}
}
and object
ClassA obj=new ClassB();
If you call obj.run() how will you know if that code is following the rules of polymorphic open/close principle or it will code method related to ClassA? In Java you will know that there is always polymorphism. It is easier to make mocks and it is easier to extend classes and follow Liskov substitution principle.
On the other hand static methods are bounded to a class so if you want to call a method that is related to ClassA you can define that method like this:
public static run(ClassA obj)
and you can call it with
ClassB obj=new ClassB();
ClassA.run(obj);
and from the code you will know that the method you are calling is defined in ClassA and not in ClassB. Also in that case you will not have the overhead of virtual methods. (Note that JIT will also reduce the overhead of virtual methods in many cases).
For C#, if the reason to make the method non-virtual is to be able to define it in a subclass but not involve polymorphism, you're probably subclassing for no real reason.
If it's for design, I'd suggest making the class sealed (final in java) instead of individual methods if possible.
Jon Skeet said that in C# the classes should be sealed by default because methods are non-virtual by default as well. Joshua Bloch said that you should design for inheritance or forbid it (make classes final). C# designers chose a hybrid approach which is non-consistent.