Would you do anything differently in developing C# if you had the chance?
There are several things. First of all, when we shipped C# 1.0 we did not have generics in the language – that came in C# 2.0, and the minute we shipped generics we were able to put a lot of old code to bed as it was superfluous and not as strongly typed as generics. So a bunch of stuff got deprecated right out of the box in C#2.0. We knew generics were coming but it was one of those hard decisions: do you hold the platform longer or do you ship now and work on this and then ship it a couple of years later? I would have loved to have generics from the beginning as it would have left us with less obsolete stuff in the framework today.
With language design or with platform design 1.0 is always a unique opportunity to put down your core values, your core designs, and then with every version thereafter it’s much harder to fundamentally change the nature of the beast. And so, the things that you typically end up regretting later are the fundamentals that you didn’t quite get right. Because those you can’t change - you can always ship new libraries etc, but you can’t change the fundamental gestalt of the platform.
For example, in the type system we do not have separation between value and reference types and nullability of types. This may sound a little wonky or a little technical, but in C# reference types can be null, such as strings, but value types cannot be null. It sure would be nice to have had non-nullable reference types, so you could declare that ‘this string can never be null, and I want you compiler to check that I can never hit a null pointer here’.
50% of the bugs that people run into today, coding with C# in our platform, and the same is true of Java for that matter, are probably null reference exceptions. If we had had a stronger type system that would allow you to say that ‘this parameter may never be null, and you compiler please check that at every call, by doing static analysis of the code’. Then we could have stamped out classes of bugs.
But peppering that on after the fact once you’ve built a whole platform where this isn’t built in… it’s very hard to pepper on afterwards. Because if you start strengthening your APIs and saying that you can’t pass null here or null here or null here, then all of a sudden you’re starting to break a bunch of code. It may not be possible for the compiler to track it all properly.
Anyway, those are just things that are tough later. You sort of end up going, well ok, if we ever get another chance in umpteen years to build a new platform, we’ll definitely get this one right. Of course then we’ll go and make other mistakes! But we won’t make that one.
Why do you think C is such a popular language base, with many languages built on it such as C++ and C#?
I think you have to take the historic view there first. If you go back to C itself, C was a very, very appropriate language for its time. It was really the language that lifted operating system builders out of assembly code and gave them higher level abstractions such as data types and so forth, yet was sufficiently close to the machine so that you could write efficient code. It was also very succinct: it was a very terse language, you can write very compact code which is something that programmers very much prefer. You compare a C program to a COBOL program and I can tell you where you’re going to see more characters.
So C was just an incredibly appropriate language for its time, and C++ was an incredibly appropriate evolution of C. Once you have huge language use, it is much easier to evolve and bring an existing base with you than it is to go create something brand new. If you look at the mechanics of new languages, when you design a new language you can either decide to evolve an existing language or start from scratch.
Evolving an existing language means you have an instantaneous big user base, and everything you add to the language is just gravy… there’s really no draw back as all of the old code still works. Start with a brand new language and you essentially start with minus 1,000 points. And now, you’ve got to win back your 1,000 points before we’re even talking. Lots of languages never get to more than minus 500. Yeah, they add value but they didn’t add enough value over what was there before. So C++ I think is a fantastic example of a very appropriate evolution of an existing language. It came right at the dawn of object oriented programming and pioneered that right into the core programming community, in a great way.
Of course by the time we started looking at C# as a new language, there was a huge, huge number of programmers out there that were very accustomed to programming with curly braces, like the C guys, C++ guys, Java guys etc etc. And so for us that was a very natural starting point: to make a language that would appeal to C++ programmers and to Java programmers. And that really meant build a language in the C heritage. And I think that has served us very, very well.