(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 C# view.

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 we're after.

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.