(The opinions expressed herein reflect my opinion about the principles we used in
designing C#, and do not necessarily reflect the opinions of the C# design team).
Know what you’re trying to build
Over the past few years, I’ve answered a lot of questions about language design rationale.
Most questions have straightforward answers. For example, if somebody asks “Why doesn’t
C# have macros?”, that’s easy to answer.
Other questions require a bit more work, and/or may be religious discussions. “Why
are methods non-virtual by default?” takes more time to answer.
The toughest ones to answer aren’t tough because they’re technically hard – they’re
tough because it’s hard to give a nice answer to. This is usually because doing what
the person requests would require changing one of the basic tenets of the language.
Our goal in C# was to create a modern, real-world managed language that would be comfortable
to developers used to the C family of languages (C, C++, Java, etc.). So, when I get
questions like, “Why is C# case-sensitive?”, they’re really hard to answer. The real
answer is that our target users would think we were crazy if we made a language that
wasn’t case-sensitive. You can say this in a polite way, but the person who asked
the question is usually confused by your response. Their perspective is often “of
course a language should be case-insensitive”, which is diametricly opposed to the
Similarly, I’ve been asked why C# doesn’t allow you to define your own operators.
There are some languages that allow you to do that, but that’s very much not what
Re-reading this, I’m not sure it’s terribly insightful, so I’ll try to summarize.
When you’re designing a language, you need to be clear up front what you’re trying
to build, and who is going to want to use that. Those early decisions are going to
have a huge impact on the design of the language, and once you’ve made them, you can’t
really go back.