Musings on many aspects of software development including methodologies, software quality assurance, software design, etc.
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
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.
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.
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.
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.)
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"
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).
Microsoft needed a new language in 1997
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.
development was painful and slow. COM was supposed to address this but
made it worse!
were a lot of error-prone areas in C/C++ that could be fixed by new syntax
were a lot of things that could be taken from C++ like exceptions,
templates and STL containers.
could wrap/hide the horrendous Windows API (like MFC did for C++).
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.)
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.
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.
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.
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.)
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.
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.
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.
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
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?
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.)
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.
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++).