Monday 8 May 2017

Why I like C#


I was going to talk a bit more about version control and Git after my posts on Agile version control late last year but I have been very busy with a new job.

“it was 20
years ago today”
However, I have had a draft of this post for many years and significantly it was 20 years ago today (actually last Thursday) that I invented C#. I remember it distinctly as a colleague suggested we go out and celebrate "Star Wars Day" after work. I had never heard of Star Wars Day (May the Fourth) before then.

It was during a jovial conversation over a few drinks that I mentioned my idea that Microsoft should invent their own language which, as it turned out, was rather like C#. The reaction was that I was a complete idiot, after all Microsoft were not known for that sort of thing - the closest they had come was COM (Component Object Model) which we had all used and agreed was an unwieldy mess. Microsoft had also invested heavily in their own dialect of Basic called VB (Visual Basic), as well as their C compiler, so why would they want a new language? This was in the days when it was novel for a company to create a language, begun, I guess with Sun and Java.

My idea was oddly triggered by my problems with the latest Visual C++ 4.0 (which we had been using for a few months). I had written a new SCSI library in C++ for some 32-bit code but was greatly dismayed to find that VC++ was not designed to create 16-bit code (for MSDOS, Windows 3.1) or even Win32s - I wanted to use the C++ code with some legacy C applications.

We had also encountered lots of frustrations with C++.  We had done a lot of stuff in C previously but needed some modern languages features. Other languages around like Delphi and Java were not suitable either.

I decided that what was really needed was a language that Microsoft would properly support (C++ support was not good at the time), had modern features that C was lacking (like templates, exceptions and even a few niceties from Java, like GC). There was also a technological development (see next), where Microsoft was at the forefront, which was crucial for my new language.

P-Code

I had been greatly intrigued by p-code since 1978 when I had first used Pascal at University. Pascal (at least the compiler I used) compiled to p-code which thence required a p-code interpreter for whatever CPU you were using. (This idea was later used Java in byte-code and .Net MSIL.) Not long after that I did a lot of programming in Forth (sort of a p-code assembler) on my Commodore 64.

The problem with p-code is that it is slow. Running p-code (via interpreter) is about an order of magnitude slower than the same program compiled to native instructions. A lot of people thought that this would become less of a problem as computers got faster. The trouble with this argument is that while the interpreted code got faster so did the native code. (The idea of p-code also seemed to be fading until Sun created Java, but a lot of people did not like the poor performance of Java.)

However, some people at Microsoft realized that once processors were fast enough you could compile on the fly (later called JIT-compilation) rather than interpret the p-code. Sooner or later the compilation time would become negligible.
"once processors
were fast enough
you could compile
on the fly"

Microsoft had done a lot of research on JIT-compilation, on their (then) flagship language VB. (Basic is an interpreted like p-code).  During the mid 1990s I did some tests and found that VB6 was similar in speed to C++ in many areas due to use of JIT-compilation. All the C++ programmers I told this to just did not believe me (or did not want to).

Why Microsoft needed a new language in 1997

  1. C (and an emerging C++) were the driving force behind almost all the successful MSDOS and Windows products and most C/C++ programmers, myself included (perhaps unfairly), avoid VB like the plague.
  2. C/C++ development was painful and slow. COM was supposed to address this but made it worse!
  3. There were a lot of error-prone areas in C/C++ that could be fixed by new syntax and semantics.
  4. There were a lot of things that could be taken from C++ like exceptions, templates and STL containers.
  5. They could wrap/hide the horrendous Windows API (like MFC did for C++).
  6. There was a lot of interest in Java (especially its innovative memory management system) but Microsoft were impeded using Java for their own ends by a litigious Sun. (Sun had already successfully sued Microsoft for not properly implementing Java.)
  7. A language like Java generating intermediate code (p-code) would be slow but this problem could be alleviated by Microsoft's research into JIT-compilation from the early-mid 1990's.

.Net and C#

I did not really think much more about it but a few years later I started hearing about NGWS, VB7 and later C#. In 2001 I downloaded and tried the C# public beta. It was then that I realized that C# was very similar to the language that I had previously been advocating. My only disappointment was that C# lacked templates and STL-like containers, though C# 2.0 later added generics.

To be fair to Microsoft (and Anders) there were a hell of a lot more great things in C# than I could ever have come up with, though many came from Java and C++. And even since then, C# has added some brilliant new things of its own, like lambdas and LINQ.

C# Problems

You may have noticed from previous posts that I like C# in many ways. I guess this may be partly due to the fact that I feel I independently invented it. However, there are a few things that it got wrong, but remember that these are very small in number compared to the large number of things it got right.  (Also note that some of these things are due to the .Net CLR upon which C# depends.)
  1. One thing that I really thought C# should have had from the start was (what came to be known as) generics. In 1997 I had become a huge fan of templates, and especially the STL, in C++. I remember reading that they would be added later (and were added in C# 2.0). Why not delay the release of C# 1.0 until they were ready? This has caused a lot of problems of maintaining backward compatibility, especially when implementing generic interfaces.
  2. I really hate the containers in C# compared to C++ STL containers or even those of other languages. Related to the previous problem is the later addition of generic containers to replace the earlier ones.
  3. Apart from the containers most of the C# run-time library is excellent. But there were some simple, obvious mistakes which I picked up straight away. An obvious one was that Int.Parse() throws an exception if it encounters a non-digit rather than the more sensible behavior of something like C's strtoi().  This was later addressed with Int.TryParse().
    Another one I encountered almost straight away is that String.Substring() throws an exception if the string is not long enough. This might be good behavior sometimes but more commonly you would just want a shorter string returned rather than throw an exception.
  1. One of the stupidest things in C# is the Decimal type. (Anders seems to have an irrational penchant for stupid numeric types such as the Delphi real48.) As soon as I saw it I thought it would be better and much simpler just to add fixed point facilities to existing integer types, attached as metadata (ie, using an attribute attached to an integer variable).

    I wrote at length about this over a decade ago - eg see Why do we need Decimal?
  2. Const is one of the simplest and most useful additions to C++. I do not know why C# (and other languages) continue to ignore it. TBD: elaborate?
  3. The fact that all static and heap variables are cleared (made zero) at run-time is sometimes unnecessary and inefficient.  What's the point of a huge array being initialized to zeros then immediately have all its values set to some other value(s)?  (Note that the security argument is a furphy.)
  4. I previously mentioned that the behavior of the default test for equality (Object.Equals()) is flawed. (See the C# section in my post on Zero).  Actually having recently used Go (the language from Google) I now realize that all the "object-oriented" stuff, that C# copies almost exactly from Java, is unnecessary and actually encourages poor designs (but at least there is no multiple-inheritance!).  I may talk about this more in a future post on Go.

Conclusion

C# made things so much easier after using C (and then C++) for decades. There are so many things I could mention but a few immediately spring to mind:
  • metadata system which avoids all sorts of configuration problems that plague C due to header files, linking issues, DLL hell, etc
  • the garbage collected heap which frees you from the tedium of having to track who allocated what and who needs to free it and making sure there are no memory leaks and double-frees, etc
But there were many other little things - for example, see the Code Project article that I wrote in 2004 called C# Overflow Checking.

Sure C# borrowed a lot of things from Java, but that is de rigeur for language design (and Java got a lot from C++).