Estou surpreso que parece haver um consenso aqui de que não virtual por padrão é a maneira certa de fazer as coisas. Vou descer do outro lado - acho pragmático - da cerca.
A maioria das justificativas me parece o velho argumento "Se dermos a você o poder, você pode se machucar". De programadores ?!
Parece-me que o codificador que não sabia o suficiente (ou não tinha tempo) para projetar sua biblioteca para herança e / ou extensibilidade é o codificador que produziu exatamente a biblioteca que provavelmente terei de consertar ou ajustar - exatamente o biblioteca onde a capacidade de substituir seria mais útil.
O número de vezes que tive que escrever um código de solução feio e desesperado (ou abandonar o uso e lançar minha própria solução alternativa) porque não posso substituir muito, supera em muito o número de vezes que já fui mordido ( por exemplo, em Java) substituindo onde o designer pode não ter considerado eu.
Não virtual por padrão torna minha vida mais difícil.
ATUALIZAR: Foi apontado [muito corretamente] que eu realmente não respondi à pergunta. Então - e com desculpas pelo atraso ...
Eu meio que queria ser capaz de escrever algo incisivo como "C # implementa métodos como não virtuais por padrão porque uma má decisão foi tomada que valorizava mais os programas do que os programadores". (Acho que isso poderia ser um pouco justificado com base em algumas das outras respostas a esta pergunta - como desempenho (otimização prematura, alguém?), Ou garantia do comportamento das classes.)
No entanto, percebo que estaria apenas declarando minha opinião e não aquela resposta definitiva que Stack Overflow deseja. Certamente, pensei, no nível mais alto, a resposta definitiva (mas inútil) é:
Eles não são virtuais por padrão porque os designers da linguagem tiveram uma decisão a tomar e foi isso que escolheram.
Agora eu acho que a razão exata pela qual eles tomaram essa decisão nós nunca ... oh, espere! A transcrição de uma conversa!
Portanto, parece que as respostas e comentários aqui sobre os perigos de substituir APIs e a necessidade de projetar explicitamente para herança estão no caminho certo, mas estão todos perdendo um aspecto temporal importante: a principal preocupação de Anders era manter uma classe ou APIs implícitas contrato entre versões . E eu acho que ele está realmente mais preocupado em permitir que a plataforma .Net / C # mude no código, em vez de se preocupar com a mudança do código do usuário no topo da plataforma. (E seu ponto de vista "pragmático" é exatamente o oposto do meu porque ele está olhando do outro lado.)
(Mas eles não poderiam simplesmente ter escolhido o virtual por padrão e, em seguida, adicionado "final" por meio da base de código? Talvez não seja exatamente a mesma coisa ... e Anders é claramente mais inteligente do que eu, então vou deixar assim.)
this
referência for nula. Veja aqui para mais informações.