A Brief History of C#
C# is a widely-used, mature, general-purpose programming language with millions of professional developers worldwide, but it was not always so.
In this article I’m going to take a brief chronological look at the past, present and future of the C# language…
The beginning: C# 1.0 (2002)
The first two sentences of the C# 1.0 specification are very clear about the design goals of the language:
C# is a simple, modern, object-oriented, and type-safe programming language. C# has its roots in the C family of languages and will be immediately familiar to C, C++, and Java programmers.
Anders Hejlsberg, chief architect of C#, once told me “new languages begin with minus ten thousand points”. The costs of creating, popularizing, maintaining and extending a language are so large that the corresponding benefits have to be enormous when compared an existing language. Thus every new language is an attempt to address the shortcomings of its predecessors, and C# is no exception.
C# 1.0 was designed specifically as a response to C++, from which it takes its basic syntactic elements. (*) The designers of C# considered carefully all of the many pitfalls that faced C++ users and devised mitigations for many of them. Some of these took the form of major departures, such as eliminating multiple class inheritance. Most were subtle, such as the rule that no name may be used to mean two different things in the same block.
The language designers placed particular emphasis on the type safety of the language. A language is said to be type-safe if the compiler forbids certain operations, such as storing a customer name in a location intended to contain a dollar amount. Type safety is a double-edged sword: though on the one hand it prevents many clearly erroneous programs from compiling, it also makes some programming techniques more difficult. C# 1.0 was designed to hit the sweet spot: it has a type system strict enough to prevent many defects while at the same time allowing developers to defer some type checking to runtime.
The result was, as the specification says, a relatively simple object-oriented language. C# 1.0, though not a childish language by any means, was certainly immature.
Increasing maturity: C# 2.0 (2005) through 5.0 (2012)
Each of the four releases of C# since the initial release has had a “headliner” features which aimed to greatly increase the representational power of the language. The headliner feature for C# 2.0 was generic types. The power, safety and performance added to the C# type system by generic types cannot be overstated; they pervade nearly every aspect of both the language and its runtime libraries and made the language what it is today.
After successfully shipping generic types the design team looked at a lot of existing code. They discovered that there were a huge number of disparate data management technologies, each with their own mutually incompatible mechanisms for sorting, searching, grouping, joining, and so on. Thus the headliner feature for C# 3.0 was Language Integrated Query or “LINQ” for short. LINQ enables developers to express concepts such as “give me the first ten customers who live in London, sorted by last name” independently of whether the customer data is in a local array, an XML document, a database, or any other storage system. The challenge in the design of C# 3.0 was to find the right balance between its powerful but hard-to-explain category theory underpinnings and the need to create an easy-to-understand syntax.
This was a controversial choice. C# developers love type safety, so any attempt to make C# less type-safe was bound to be met with resistance. The design team went through several cycles of suggesting a feature, having it thoroughly criticized by a carefully selected group of developers, and going back to the drawing board. Eventually they found a satisfactory balance between safety, usability and performance, and a way to explain the feature to a skeptical user base: if you are writing a C# program that interoperates with objects designed for use in a dynamic language then you have already given up on type safety for that portion of your program! Rather than characterizing dynamic language interoperability as decreasing the type safety of C#, the feature actually makes existing non-safe portions of the program easier to understand and maintain. That code is therefore more likely to be correct even in the absence of compiler-enforced type safety.
For C# 5.0, once again the design team looked at the pragmatic needs of developers and discovered that many line-of-business programs now need to deal with latency. There is an enormous gap in time – potentially billions of machine cycles – between when some data is requested and when it becomes available. The speed of light is only so fast and the machine with the data you need could be on another continent, so you’re going to have to wait for it. Writing programs that both make efficient use of processors and present smooth, fluid user interface experiences in a world with high latency is famously difficult in traditional object-oriented languages. By creating a new asynchronous wait operator, C# 5.0 programs that use asynchrony are as easy to write as traditional synchronous programs.
The common thread is that in every version since C# 1.0 the designers of C# have looked to the pragmatic needs of professional developers and addressed those needs by adding syntax which makes the C# language more naturally express the meaning intended by the developers.
The Future of C#
For many years Microsoft has been re-architecting the C# (and Visual Basic) compiler into a “compiler as a service”, known by the code name “Roslyn”. Microsoft will soon provide the lexical, syntactic and semantic analysis engines used by the compiler and Visual Studio IDE as documented, supported libraries for the first time. This will have two major effects.
First, the general availability of the same libraries used by Microsoft to analyze C# will greatly lower the costs to third parties wishing to build analysis tools. Third party analysis tools that help developers understand, explore, maintain, organize, annotate, document, refactor and debug C# code will proliferate. C# developers love tools that help them make their code better.
Second, the new underlying architecture will make it much easier for Microsoft to innovate in the language. We should expect that C# will continue to evolve over the next few releases. There are many small “pain points” that have gone unmitigated and many small developer productivity features that have gone unimplemented because they never made it high enough on the long list of potential improvements. And the C# design team will continue to keep a close eye on major trends in the industry. The C# language has a long future ahead of it; I’m looking forward to finding out what happens next.
(*) Though C# was also a strategic response to Java, from a language design point of view both C# and Java were responses primarily to C++.