C# Design Principle: Know what you’re trying to build

(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.

Comments (5)

  1. Val Savvateev says:

    Doesn’t it all come down to trivial "know your user requirements upfront"?

  2. Eric Gunnerson says:

    I think there’s something beyond that, a more philosophical perspective on what you’re trying to accomplish it. Some of this may be broken down to user requirements, but you still need to know (for example) what it means for a language to be "comfortable for C/C++ users".

  3. orangy says:

    IMO the most complex thing here is not design a language, but maintain its evolution in the same mood 😉

  4. Dave says:

    Actually, I’ll use the normal comment mechanism to sneak in one of those (probably more annoying) questions: Why, in C#, when creating an enumeration that specifies the underlying type, must the developer use only the "byte, sbyte, short, ushort, int, uint, long ulong" forms rather than System.Byte, etc? When confronted with this compiler difference (i.e. in treatement of byte and System.Byte), it raises a doubt as to the underlying assumption that byte and System.Byte are the same construct. Very jarring when you first encounter it. *grins* No religious opinions here, just cautious dubiousness that feeds a question.

  5. Eric Gunnerson says:

    IIRC, this was true in VS2002, but I think that we fixed it in 2003, so you can use System.Byte if you want to.