Minus 100 points


When I switched over the C# compiler team, I had hoped that I would be able to give some insight into how the design team works, what decisions we make, etc. Language design is a very esoteric field, and there’s not a lot written about it (though “Design and evolution of C++“ is a pretty good read). I had hoped that I would be able to do this with concrete examples, as that makes it much easier.


I’ve been watching for candidate topics to write about, but haven’t yet come up with any good ones. One of the problems is that features have a tendency to morph in design (and in whether they’ll make it into Whidbey) as time goes by, and it would be bad for me to say, “we’re talking about doing<x>“ and then have us decide it wasn’t a good idea. Or, for us to decide that <x> doesn’t fit into our schedule, or it would break existing code, or any of the other reasons that might cause us to pull a feature. We’re generally not comfortable really talking about those things until the feature is in somebody’s hands.


In lieu of such an example, I’ve decided to write something a bit more abstract about how we look at things.


******


I’ve been spending a lot of time answering customer questions about why we do (or don’t) have certain language features in C#. (as an aside, yes, we will be getting more of this online on the C# dev center).


In some of those questions, the questions asks why we either “took out” or “left out” a specific feature. That wording implies that we started with an existing language (C++ and Java are the popular choices here), and then started removing features until we got to a point where we liked. And, though it may be hard for some to believe, that’s not how the language got designed.


One of the big reasons we didn’t do this is that it’s really hard to remove complexity when you take a subtractive approach, as removing a feature in one area may not allow you to revisit low-level design decisions, nor will it allow you to remove complexity elsewhere, in places where it support the now-removed feature.


So, we decided on the additive approach instead, and worked hard to keep the complexity down. One way to do that is through the concept of “minus 100 points”. Every feature starts out in the hole by 100 points, which means that it has to have a significant net positive effect on the overall package for it to make it into the language. Some features are okay features for a language to have, they just aren’t quite good enough to make it into the language.


A feature like expression filters in VB is in this bucket. Yes, being able to put a condition on a catch is somewhat more convenient than having to write the test yourself, but it doesn’t really enable you to do anything new.


Being able to have property accessors with different accessibilities was another example of this. We had some experience with users being able to specify different levels of virtual-ness (virtuality?) on different accessors in an early version of the language, and it was a really confusing feature, so we elected to remove it. We felt similarly about differing accessibilities, and so we left it out of the 2002/2003 versions of the language, but we got *so much* feedback from customers that we re-evaluated the utility of the feature, and decided to add it to the language in the Whidbey version.


One can argue that we should perhaps have come to that conclusion earlier, but I don’t think that being cautious is a bad thing when doing language design. Once you add a feature, it’s in the language forever.


I should also probably note that this isn’t the only reason features don’t make it into the language. Some features provide enough utility in the abstract, but when we go to come up with a workable design for the feature, we find that we can’t come up with a way to make it simple and understandable for the user. That means that in some cases we like a feature in the abstract, but it’s not in the language.


There is also another class – features that we don’t want to get near the language. But that would be another post.


Comments (26)

  1. Daniel O'Connell says:

    <quote>

    There is also another class – features that we don’t want to get near the language. But that would be another post.

    </quote>

    However that would likely be a very insightful post, I am curious if the C# teams idea of what shouldn’t be in the language is similar to what I think shouldn’t be

  2. James High says:

    I too would love to read some insights about why the team feels certain features should be kept out of the language spec.

  3. Keith Hill says:

    But expression filters do allow you to do something new. Have you ever tried to generate your own minidumps? In order to generate a valid minidump file (by calling MiniDumpWriteDump) you have to be hooked into the first pass stack walk during exception processing. In C, I do this like so:

    __try { … }

    __except (MiniDumpWriteDump(…), 1) { … }

    The point is that you can’t put the call to MiniDumpWriteDump() in the catch block itself because by that point we are in the second pass and the stack has been unwound from the location of the throw/fault up to the catch handler. This thwarts error handling/logging capabilities.

    Another effect of not having expression filtering is that you wind up catching exceptions you didn’t want to catch so you rethrow the exception. That’s expensive and slows exception processing even more. At this point w/2.0 features, this one feature is the one major missing feature IMO. BTW, please don’t put "With" into the language. I keep hearing VB converts ask for this one and I despise the feature.

  4. Daniel O'Connell says:

    Not to take this into religious territory, but in that situation I feel exception filters are being abused. I’d rather see the language(framework?) come up with a better method of managing logging without having to resort to filter hacks. A specific handler type for logging perhaps would be better(always called on the first pass with full information, after that fault handlers are dealt with). If its possible to hack it, its possible to do it nicely.

    However, I do agree with you on the "With", 😉

  5. Ryan Heath says:

    <quote>

    There is also another class – features that we don’t want to get near the language. But that would be another post.

    </quote>

    So when will this be posted? 😉

  6. Bart says:

    Being someone that likes the With from delphi, whats wrong with it?

  7. Keith Hill says:

    <quote>

    Being someone that likes the With from delphi, whats wrong with it?

    </quote>

    Because one of the benefits of C# is its simplicity. In 1.0 there are only about 77 keywords. You can easily do without "With" by just assigning to an intermediate variable. That’s just my opinion of course.

    <quote>

    in that situation I feel exception filters are being abused. I’d rather see the language(framework?) come up with a better method of managing logging without having to resort to filter hacks.

    </quote>

    I’d be OK with that as long as I can get valid minidumps. Though you still have the performance issue with the rethrow.

    <quote>

    There is also another class – features that we don’t want to get near the language. But that would be another post.

    </quote>

    I am guessing it is checked exceptions although this is probably more of a CLR feature than a language feature.

  8. dave says:

    <quote>

    I am guessing it is checked exceptions although this is probably more of a CLR feature than a language feature.

    </quote>

    IIRC, java checked exceptions are at the language level, not the VM level. for example, I believe a compiler could generate valid java bytecode that contains code that throws a checked exception, w/o the enclosing method having declared it.

  9. Daniel O'Connell says:

    <quote>

    <quote>

    in that situation I feel exception filters are being abused. I’d rather see the language(framework?) come up with a better method of managing logging without having to resort to filter hacks.

    </quote>

    I’d be OK with that as long as I can get valid minidumps. Though you still have the performance issue with the rethrow.

    </quote>

    In the case of the rethrow issue, I feel thats the ideal reason for exception filters, to only handle what you need. Writing mini-dumps just seems hacky, I’d rather see something like

    try

    {

    }

    catch

    {

    }

    log

    {

    WriteMiniDump()

    }

    finally

    {

    }

    than a catch that does nothing but create a minidump.

  10. Keith Hill says:

    <quote>

    IIRC, java checked exceptions are at the language level, not the VM level.

    </quote>

    Since .NET supports multiple languages, in order for this feature to be practical all languages should support. Hence, the feature would probably be implemented in the CLR and languages would expose it.

  11. Mike Dimmick says:

    The rethrow doesn’t just cause a performance issue (although it does), it also loses the original context of the exception, IIRC.

  12. Eric says:

    I’ll consider writing "things that I think should never be in the language".

    On the subject of exception filters, we wouldn’t rate performance in the exception case highly, as the exception case is supposed to be just that, exceptional.

    It’s also tht case that if you use "throw" in your catch, you don’t lose your exception context. You do lose it if you use "throw e".

  13. Shawn says:

    Some like the "with" some don’t. There’s nothing wrong with that keword and its functionality. Most VB programmers don’t have a problem understanding it and rarely, if ever, does it prohibit productivity. C#/Java programmers on the other hand, seem to be scared of the feature. They act as if all of the sudden, their project is going to slip behind schedule, bugs are going to creep in, the code will somehow morph itself into an unreadably mesh and goop of speghetti code.

    It’s actually quite funny to watch the reaction of a c# programmer overlooking a piece of VB that uses "with". Sometimes I wish I had a camera.

    They feel as if it’s "improper" design. "Just throw in an intermediate variable" they say. I fail to see how an "intermediate variable" is any better (of course, they both compile to the same thing, but in my experience, of which there is much much much, code is easier to read without intermediate reference variables). Of course, a "with" block that is too large to too nested can be a problem but even so, in that case, I’ve still never lost an ounce of productivity either writing it or inheriting it. I’ve never once in my 7 years working with VB had to make a change to something relating to a "with" block. 10 out of 10 times, it’s something else. But that’s just me. And I have worked for a few software houses and done much consulting.

    But all this is moot. C# will never get the feature anyway. The C# team has spoken. I dissagree with their reasons, I think they are too lazy, personally, and most unreceptive to change. But, I can respect them not wanting to "complicate" it. As if VB is complicated because of that feature. And if they did add it, I would get a real kick out of the reaction of the general C# public. And I will jsut be waiting to hear how many projects slipped past schedule because of that keyword and how many mission-critical apps fail. I bet, just maybe, there won’t be any. The world won’t come to an end. But the whining also won’t come to and end.

    Thanks,

    Shawn

  14. Fred says:

    It’s actually quite funny to watch VB programmers whine about the "with" keyword. I’ve never once in my 7 days of working with VB, had to use "with" to do anything useful.

    But this is moot because the C# team is lazy and most unreceptive to change. They’re so lazy, I don’t see how they were even able to design a language millions of people use. Besides, if they added the "with" keyword, Eric Gunnerson’s sump pump would mysteriously break down and flood his house. Repeatedly.

  15. Shawn says:

    If "with" is so evil, then why were there no articles or complaints about it until C# programmers decided it was "evil(tm)"?

    Anyway, I was referring to their reasons why not to implement the feature.

    Personally, I don’t care one way or the next. But anytime a C# programmer expresses why they don’t want it, I feel the need to express why it’s not a bad thing to have it.

    Thanks,

    Shawn

  16. Shawn says:

    Fred, I’m sure there are other features in VB that you haven’t encountered in your "7 days of working with VB" to do anything useful, but that doesn’t mean those features you didn’t use aren’t useful, productive, and overall, good features.

    So let me clarify a previous remark. I’m not intentionally condemning C# programmers (I am one myself, as well as a win32 assembly programmer, and C/C++ (but not Java) programmer). I’m simply stating that the inclusion and/or exclusion of the feature isn’t the end of the world. The VB community wasn’t complaining about any shortcomings of the feature before C# came out, and still aren’t. Only C# programmers are complaining about it, and the VB programmers are complaining about the C# programmers complaining.

    The only reason I use VB (apart from the company requiring it) is because a) I like it. b) At times, it is more productive than C# (for reasons I won’t list here, but there are a few good ones).

    C# is a great lenguage.

    Regarding the blog entry: I’m impartial to the Exception Filtering feature being added to C#. I’ve never used it in VB and haven’t found the need to use. Because I haven’t used it, I won’t comment whether it should be added/removed as I can’t comment on it’s usefulness or productivity factor. Nor has anyone on any time I’v lead had a problem with it’s presence/absence (in C#/VB.NET).

    Thanks,

    Shawn

  17. Shawn said: It’s actually quite funny to watch the reaction of a c# programmer overlooking a piece of VB that uses "with". Sometimes I wish I had a camera.

    This is so true! They freak right out when they first see it. They think "Holy crap! there’s gotta be something inherantly wrong about that!!"

    But when they understand it they tend to happily coexist with it.

    When you force one of these poor little C# coders to work in VB, they won’t use "with" themselves, but they also won’t refactor it out of code that does use it.

    It’s just one of those bi-culturalist things.

    I’m happy for them to not have. And it’s a wise and prudent decision on the part of the C# team to not let things into the language until they’ve very strongly proven their own wirth. i mean, worth.

    keep up the bloggin eric!

  18. Niall says:

    With regard to:

    <quote>

    In some of those questions, the questions asks why we either “took out” or “left out” a specific feature. That wording implies that we started with an existing language (C++ and Java are the popular choices here), and then started removing features until we got to a point where we liked. And, though it may be hard for some to believe, that’s not how the language got designed.

    </quote>

    I am curious as to why the C# syntax for a finalizer is the destructor syntax. It doesn’t bother me one way or another, but I am still curious.

    Given the minus 100 points idea, I’m curious to see how the destructor syntax could have gained 100+ points to get into the language. As far as I can see, its only benefit is that C++ programmers would be familiar with it. But on the negative side, the difference between a finalizer and a destructor may be missed because of the syntax.

    So am I not seeing some other benefit of using the destructor syntax?

    Niall

  19. Thanks for the insight, Eric.

    Any chance of the "ask the designers" column starting up again on your MSN community site?

  20. A language design question was posted to the Microsoft internal C# discussion group this morning: " Why

  21. An attentive reader pointed me at this long thread on a third-party forum where some people are musing

  22. User : The typeof(T) operator in C# essentially means “compiler, generate some code that gives me an

  23. Пользователь: Оператор typeof(T) в C#, по существу, означает «компилятор, сгенерируй некий код, который