Я удивлен, что здесь, кажется, существует такой консенсус, что не виртуальный по умолчанию является правильным способом сделать что-то. Я собираюсь спуститься на другую - я думаю, прагматическую - сторону забора.
Большинство оправданий читаются мне как старый аргумент «Если мы дадим вам силу, вы можете навредить себе». От программистов?!
Мне кажется, что кодер, который не знал достаточно (или не имел достаточно времени), чтобы спроектировать свою библиотеку для наследования и / или расширяемости, - это кодер, который создал именно ту библиотеку, которую мне, скорее всего, придется исправить или настроить - именно та библиотека, в которой возможность переопределения будет наиболее полезной.
Сколько раз мне приходилось писать уродливый, отчаянный обходной код (или отказываться от использования и накатывать свое собственное альтернативное решение), потому что я не могу переопределить слишком далеко, намного превышает количество раз, которые я когда-либо был укушен (например, в Java) переопределением там, где дизайнер, возможно, не учел, я мог бы.
Не виртуальный по умолчанию делает мою жизнь сложнее.
ОБНОВЛЕНИЕ: Было указано [совершенно правильно], что я на самом деле не ответил на вопрос. Так что - и с извинениями за опоздание ....
Я хотел бы написать что-то наподобие «C # реализует методы как не виртуальные по умолчанию, потому что было принято неверное решение, которое оценивает программы выше, чем программисты». (Я думаю, что это может быть несколько оправдано, основываясь на некоторых других ответах на этот вопрос, таких как производительность (преждевременная оптимизация, кто-нибудь?) Или гарантия поведения классов.)
Однако я понимаю, что просто излагаю свое мнение, а не тот окончательный ответ, который желает переполнение стека. Конечно, я думал, что на самом высоком уровне окончательный (но бесполезный) ответ:
По умолчанию они не виртуальны, потому что разработчики языка должны были принять решение, и именно это они и выбрали.
Теперь, я думаю, точную причину, по которой они приняли это решение, мы никогда ... о, подождите! Стенограмма разговора!
Таким образом, кажется, что ответы и комментарии здесь об опасностях переопределения API и необходимости явного проектирования наследования находятся на правильном пути, но все они упускают важный временный аспект: главная задача Андерса заключалась в поддержании класса или неявный контракт API между версиями . И я думаю, что он на самом деле больше заботится о том, чтобы позволить платформе .Net / C # меняться под кодом, а не беспокоится об изменении кода пользователя поверх платформы. (А его «прагматичная» точка зрения является полной противоположностью моей, потому что он смотрит с другой стороны.)
(Но разве они не могли просто выбрать виртуальный по умолчанию, а затем перенаправить «финал» через кодовую базу? Возможно, это не совсем то же самое ... и Андерс явно умнее меня, поэтому я позволю этому ложь.)