6

Methods in C# are non-virtual by default. This answer to another question explains the advantage of doing it this way:

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.

Even Anders Hejlsberg seems to give the same reason:

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. [...] You don't want users overriding and hooking at any arbitrary point in an API, because you cannot necessarily make those promises.

I agree with this reasoning: Usually when I create a non-private method, I just want to create code that can be called from somewhere outside the class. Usually, no thought is given to how somebody else might override this method and which effect that would have. For the special cases, I can use virtual to signal that did create the code in a way where overriding makes sense.

However, classes still unsealed by default. The default assumes that I spend the extra effort of making sure that inheriting a class makes sense.

Is there anything that makes a class different from a method in this regard?


EDIT
I don't really know what to change about the on hold - opinion based thing. I never asked for opinions. Maybe I have to say it explicitly?

I don't want opinions.

A correct answer would either provide an example of a class being different from a method, or state that there is no difference in this context.

Raphael Schmitz
  • 551
  • 5
  • 19
  • 5
    By "virtual by default" I think you mean "unsealed by default", right? *Virtual" is not an adjective we usually apply to classes. – Eric Lippert May 06 '19 at 14:42
  • 1
    Why does the title say methods are virtual by default while the first sentence of the question says they're non-virtual by default? –  May 06 '19 at 14:48
  • @Amy Yeah now i just got completely confused with the terminology :D thank you, I adjusted that. – Raphael Schmitz May 06 '19 at 14:49
  • 1
    The logic of "opinion based" is that a why (or why not) question where the answer is only known definitively by a handful of people tends to attract answers that are unsourced opinions, rather than facts. I disagree with this assessment, and prefer to close such questions as "unclear what you're asking" since "why" and "why not" questions are often very vague. This is a good example of a well-written "why not?" question; it's clear why you're asking and what kind of explanation you're looking for, and you've done your research, so thanks for that. – Eric Lippert May 06 '19 at 15:44

1 Answers1

10

I believe the question is "given that there are good reasons why methods should be non-virtual by default, why are classes not also sealed by default?"

One could also add: C# makes the default accessibility either internal, for top-level types, or private, for members of types; that is, it chooses the more restrictive and safer option; if a developer wishes a less restrictive, more dangerous option they can opt into it. Sealing by default would also be choosing the more restrictive and safer option as the default.

Also: unsealing a class is never a breaking change, but deciding later that you wish you'd made a class sealed and sealing it is a breaking change. C# typically prefers the design choice that encourages fewer breaking changes, so for this reason also, you would think that C# classes should be sealed by default.

We've identified three reasons why sealed by default is both a good idea and consistent with other design choices in C#. Why then is C# inconsistent in this regard, choosing to make unsealed classes the default?

I don't know. It's always struck me as a minor design flaw in C#. I've never seen a cogent argument for this choice, and I do not know if it was debated in early design meetings or not; that was before my time on the design team.

Unless you run into someone who was in that design meeting in 2001 and ask them, you might not get a satisfactory answer to your question.

I am in the habit of sealing every class I write unless I have a reason to design it for inheritance; I encourage everyone to do the same.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 3
    And if sealing a class is a breaking change, changing the _default_ behavior now would be a devastating one. – C.Evenhuis May 06 '19 at 14:57
  • 1
    I have to admit that I'm a little mad. After I take over half an hour to write this question, you write a _better_ version of my question _and_ answer it in <6 minutes. :D What can I say though, it's a good answer, +1 – Raphael Schmitz May 06 '19 at 15:00
  • 2
    @C.Evenhuis: That's correct; this behavior cannot be changed now without causing far more harm than it would prevent. – Eric Lippert May 06 '19 at 15:00
  • 3
    @RaphaelSchmitz how about reading Eric's article [**Why Are So Many Of The Framework Classes Sealed?**](https://blogs.msdn.microsoft.com/ericlippert/2004/01/22/why-are-so-many-of-the-framework-classes-sealed/) there as it does explain well about sealed classes. – Trevor May 06 '19 at 15:02
  • 4
    @RaphaelSchmitz: Six minutes, plus the seven years of studying the design of C# for eight hours a day. It was not my intention to make you mad. – Eric Lippert May 06 '19 at 15:02
  • @EricLippert Not really mad, thank you for your answer :D – Raphael Schmitz May 06 '19 at 15:03
  • @Çöđěxěŕ Well, it argues for making classes sealed, but I already favor sealed over unsealed. – Raphael Schmitz May 06 '19 at 15:23
  • This is a bit late now, but I noticed that this might be a technical interpretation of the open-closed principle. A non-`sealed` C# class is "open" because we can still add data or behavior. A class without any `virtual` keyword is quite rigorously "closed", because you can not change what's already there. The open-closed principle is by now a bit antiquated, but around year 2000, when C# was started, it was still going strong. – Raphael Schmitz May 22 '19 at 12:49