Version summaries - C# in Depth (2012)

C# in Depth (2012)

Appendix C. Version summaries

The version numbers in .NET can be confusing sometimes. The framework, runtime, Visual Studio, and C# are all numbered separately. This appendix is a quick guide to how they fit together and the major features in each release. In each case, I’ve described the features from releases 2.0 and upward; listing all the features of .NET 1.0 and 1.1 would be fairly pointless.

C.1. Desktop framework major releases

When developers refer to releases of .NET, they usually mean the major releases of the desktop framework. In most cases, a framework release has been accompanied by a release of Visual Studio (or Visual Studio .NET, as it was named for the 2002 and 2003 releases). The exception to this was .NET 3.0, which was essentially only a set of libraries (although those libraries were pretty significant). A set of Visual Studio 2005 extensions was made available for the new features, but Visual Studio 2008 contained more support. Table C.1 shows which version of which aspect of the framework was released when.

Table C.1. Desktop framework releases and their components



Visual Studio



February 2002





April 2003





November 2005





November 2006


(Extensions to 2005)



November 2007




2.0 SP1

April 2010




4.0 (there was no version 3.0)

August 2012




4.0 or 4.5[a]

a This depends on your point of view. You’ll find out more later.

When .NET 3.5 was released, .NET 2.0 SP1 and .NET 3.0 SP1 were also released; these contained the 2.0 SP1 CLR and BCL. Similarly, .NET 3.5 SP1’s release coincided with .NET 2.0 SP2 and .NET 3.0 SP2.

Visual Studio 2008 was the first release to support multitargeting, allowing you to choose which version of the framework you want to build for. In many cases, you can use new features of C# while targeting an earlier release—this is basically the case if the feature is implemented solely by compiler magic, without any support from the CLR or libraries. More information on how to do this is available on the book’s website (see—in some cases there are workarounds if a feature doesn’t quite work out of the box. It’s worth noting that if you target .NET 2.0 (you can’t target 1.0 or 1.1) from Visual Studio 2008 or 2010, you’ll actually be targeting the relevant service pack (2.0 SP1 or 2.0 SP2); this means it’s possible to build code that uses new features from a service pack (one notable introduction was System.DateTimeOffset in 2.0 SP1) and then find it fails if you try to run it on a machine that genuinely has the original release of .NET 2.0. Personally, I’d try to update machines to at least run the latest service pack, and ideally a more recent full framework release.

C.2. C# language features

If you’ve read the whole book, you should be able to write this section yourself. (It’s tempting to leave a bunch of blank lines for you to fill in, but I’m not quite that lazy.) One trivial fact: the version number of 1.2 in table C.1 isn’t a typo; looking at the specifications, Microsoft really did skip 1.1 in order to release a C# 1.2 compiler with .NET 1.1. The changes in version 1.2 were mostly minor, but there was one significant change in the long term: it’s only from C# 1.2 and onward that the translated code for a foreach loop tests whether the iterator implementsIDisposable and disposes of it accordingly. As you’ve seen, this change is crucial for iterator blocks that have resources to clean up.

Anyway, for the sake of completeness, here are the language features, along with the chapter references for more details.

C.2.1. C# 2.0

The major features of C# 2 were generics (see chapter 3), nullable types (chapter 4), anonymous methods and other delegate-related enhancements (chapter 5), and iterator blocks (chapter 6). Additionally, several smaller features were introduced: partial types, static classes, properties with different access modifiers for getters and setters, namespace aliases, pragma directives, and fixed-sized buffers. See chapter 7 for more details.

C.2.2. C# 3.0

C# 3 primarily built toward LINQ, although many features are useful elsewhere. Automatic properties, implicit typing of arrays and local variables, object and collection initializers, and anonymous types are all covered in chapter 8. Lambda expressions and expression trees (chapter 9) extended the delegate-related progress made in version 2.0, and extension methods (chapter 10) provided the last ingredient for query expressions (chapter 11). Partial methods were only added in C# 3, but are covered with the inclusion of partial types in chapter 7.

C.2.3. C# 4.0

C# 4.0 has some features aimed at interoperability but doesn’t have the same single-mindedness of C# 3.0. Again, there’s a reasonably clear divide between the small features shown in chapter 13 (named arguments, optional parameters, better COM interop, generic variance) and the huge feature of dynamic typing (chapter 14).

C.2.4. C# 5.0

C# 5.0 is all about the asynchrony we saw in chapter 15, with two other very small features (changes to foreach variable capture, and caller info attributes) sneaking into chapter 16. Even though asynchrony only introduces a single new kind of expression (await, within an asyncfunction), it changes the execution model enormously. I’d argue that even if the C# team had been ready to deliver other large new language features (and for all I know, they were), holding them back for a while would be a sensible option. It’s important that the C# community really looks at async/await carefully, and that will take time.

C.3. Framework library features

It’d be impossible to list all of the new features in the framework in a sensible fashion here. In particular, each area of the framework (Windows Forms, ASP.NET, and so on) gets extra features in each release—not just the core base class library. I’ve included the features I believe are the most important highlights. MSDN has a far more comprehensive list at

C.3.1. .NET 2.0

The biggest features in the 2.0 libraries supported features of the CLR and languages: generics and nullable types. Whereas nullable types didn’t require many changes, several of the generic collections you’re used to now have been present since .NET 2.0, and the reflection API had to be updated accordingly.

Many areas received relatively minor updates, such as support for compression, multiple active result sets (MARS) over a single connection to SQL Server, and many static helper I/O methods such as File.ReadAllText. It’s probably fair to say that these weren’t as significant as the changes to user interface frameworks.

ASP.NET gained master pages, precompilation abilities, and various new controls. Windows Forms took a big leap in terms of layout abilities with TableLayoutPanel and similar classes, as well as gaining better support for performance enhancements such as double buffering, a new data binding model, and ClickOnce deployment. BackgroundWorker was introduced in .NET 2.0 to make it easier to update a UI safely in multithreaded applications; it’s not strictly part of Windows Forms, although that was its primary use case until Windows Presentation Foundation arrived in .NET 3.0. Speaking of which...

C.3.2. .NET 3.0

.NET 3.0 was somewhat curious as a major release with no CLR changes, no language changes, and no changes to existing libraries. Instead, it consisted of four new libraries:

· Windows Presentation Foundation (WPF) is the next-generation user interface framework; this was a revolution rather than an evolution of Windows Forms, although the two can live side by side. It has a very different model from Windows Forms, being much more compositional in nature. Silverlight’s user interface is based on WPF.

· Windows Communication Foundation (WCF) is an architecture for building service-oriented applications; it’s extensible rather than being limited to a single protocol and aims to unify the existing RPC-like communication channels, such as remoting.

· Windows Workflow Foundation (WF) is a system for building workflow applications.

· Windows CardSpace is a secure identity system.

Of these four areas, WPF and WCF have flourished, whereas WF and CardSpace appear not to have taken off so well. That’s not to say that the latter technologies aren’t being used, or that they won’t become more important in the future, but they’re not nearly as widespread as I write this.

C.3.3. .NET 3.5

The big new feature in .NET 3.5 was LINQ, supported by C# 3.0 and VB 9. This included LINQ to Objects, LINQ to SQL, LINQ to XML, and expression tree support underlying it.

Other areas also gained important features: it became a lot easier to use AJAX in ASP.NET, WCF and WPF each gained a whole host of improvements, an add-in framework (System.AddIn) was introduced, various new cryptography algorithms were included, and much more. As a developer interested in both concurrency and time-related APIs, I feel obliged to draw your attention to the introduction of ReaderWriterLockSlim and the much-needed TimeZoneInfo and DateTimeOffset types. If you’re using .NET 3.5 or higher but are still relying on DateTimeeverywhere, you should be aware that there are better options available.[1]

1 My personal feeling is that this still isn’t enough support for the complex and intriguing world of dates and times, which is why I started the Noda Time project (see, but at least with TimeZoneInfo there’s finally a clean way of representing a time zone other than the local one.

.NET 3.5 SP1’s most notable library features were the Entity Framework and related ADO.NET technologies, but other technologies had minor improvements as well. Also importantly, .NET 3.5 SP1 introduced the Client Profile—a smaller version of the desktop .NET Framework that doesn’t include a lot of the libraries aimed at server-side development. This allows a smaller deployment footprint for client-only applications.

C.3.4. .NET 4

A lot of work went into the .NET 4 libraries for a long time, in various guises. The DLR is a huge addition, and you’ve also seen (very briefly) Parallel Extensions in other chapters. As usual, the user interface technologies have a raft of improvements, although notably the focus for rich client changes is WPF rather than Windows Forms. A lot of tweaks have been made to existing core APIs to make them that much easier to use, such as String.Join accepting an IEnumerable<T> instead of insisting on a string array. These aren’t earth-shattering improvements, but if they make every developer’s life just a little bit simpler, that can have a large cumulative impact. You’ve already seen how some of the existing generic interfaces and delegates have become covariant or contravariant (IEnumerable<T> becoming IEnumerable<out T> and Action<T>becoming Action<in T>, for example) but there are new types to explore as well.

There’s a new namespace for numerical calculations, System.Numeric. At the time of this writing, it only contains the BigInteger and Complex types, but I wouldn’t be surprised to see BigDecimal join them in the future. There are other new types within the System namespace, such as Lazy<T> for lazily initialized values and a Tuple family of generic classes that provide the same sort of functionality as the Pair<T1, T2> class from chapter 3, but for up to eight type parameters. Tuple also supports structural comparisons, as represented by the newIStructuralEquatable and IStructuralComparable interfaces in the System.Collections namespace. Although the full Reactive Extensions classes you saw in chapter 12 aren’t in .NET 4, the core interfaces IObserver<T> and IObservable<T> are in the Systemnamespace. I’ve brought up these specific items because although new areas like the Managed Extensibility Framework (MEF) get a lot of attention, it’s easy to overlook simple types like these. It’s good to see that time is being spent on the whole framework, not just on shiny new cool stuff.

C.3.5. .NET 4.5

Again, the biggest driver in .NET 4.5’s changes is almost certainly asynchrony. There are asynchronous versions of just about every API you could want one for: if it could take a while, you should be able to do it asynchronously. The Task Parallel Library from .NET 4 has been expanded (and optimized) to help with this too.

There are lots of other changes within .NET 4.5, and it would be foolish to try to describe all of them. Even the MSDN page listing the highlights ( is longer than I’d want to include here. But most of those changes will depend on the project you’re building, whereas the sweep of asynchrony across the whole platform is likely to impact everyone, over time.

C.4. Runtime (CLR) features

CLR changes are often less visible to many developers than new library and language features. Obviously there are some particularly shiny features such as generics that’ll catch everyone’s attention, but others are less obvious. The CLR has also changed less frequently than either the language or the framework libraries, at least in terms of major releases.

C.4.1. CLR 2.0

In addition to generics, the CLR required one extra change to support the new language features of C# 2: the behavior of boxing and unboxing nullable value types that we explored in chapter 4.

CLR 2.0 had other major changes. The most significant ones were support for 64-bit processors (both x64 and IA64) and the ability to host the CLR within SQL Server 2005. The SQL Server integration required new hosting APIs to be designed, so that the host could have a lot more control over the CLR, including how it allocates memory and threads. This allows a diligent host to make sure that code running in the CLR won’t compromise other aspects of a critical process, such as a database.

.NET 3.5 included CLR 2.0 SP1, and .NET 3.5 SP1 included CLR 2.0 SP2; these had relatively minor changes, such as tweaks to the access that code in a DynamicMethod has to private members of another type. The CLR team is always looking for ways to improve performance as well, with improvements in garbage collection, the JIT, startup times, and so on.

C.4.2. CLR 4.0

Although the CLR didn’t need to change in order to accommodate the DLR, the team has still been hard at work. These are some of the highlights:

· Interop marshaling performance and consistency improvements with IL stubs everywhere (see this .NET Framework Blog post for details:

· A background garbage collector to replace the concurrent collector in CLR 2.0

· An improved security model based on the concept of transparency, which is the successor to Code Access Security (CAS)

· Type equivalence, used to support the embedded PIA feature of C# 4

· Side-by-side execution of different CLRs within the same process

The CLR in .NET 4.5 includes a number of improvements, mostly around garbage collection. You can think of it as a minor release, effectively. Alongside pure performance benefits, the 64-bit CLR also supports the <gcAllowVeryLargeObjects> configuration option, which allows for the creation of enormous arrays, even when the elements are large structures...assuming you have the memory, of course. In terms of the version number, the picture is slightly complicated. In documentation, you may well see this version of the CLR referred to as CLR 4.5. However, it still advertises itself as 4.0 if you consult the Environment.Version property. For example, at the time of writing the CLR I’m running reports version 4.0.30319.18033. The build and revision numbers may potentially change over time due to service packs.

More details of all of the new features are available on the .NET Framework Blog (

C.5. Related frameworks

It’s rare for anything in computing to do well with a one-size-fits-all model, and .NET is no exception. Even the desktop framework isn’t really a single version: there’s the client profile, the 32-bit and 64-bit JITs, and the server and workstation CLRs tuned for different tasks. Beyond that, there are separate frameworks that have their own version histories, tailored to different environments.

C.5.1. Compact Framework

The Compact Framework was originally aimed at mobile devices running Windows Mobile. Since then, it’s been retargeted for Xbox 360, Windows Phone 7, and Symbian S60.

The Compact Framework major release schedule has traditionally mirrored that of the desktop framework, although there’s no release corresponding to .NET 3.0. Just to keep things interesting, the most up-to-date release (used by some Windows Mobile devices and WP7) is version 3.7.

Early versions of the Compact Framework were missing some fairly core functionality, which was largely filled by community efforts; later releases have plugged many of the more significant gaps, although obviously it’s still a subset of the desktop framework. The GUI layer depends on the exact platform; for example, on the Xbox 360 you’d use XNA, Windows Mobile supports Windows Forms, and WP7 supports both XNA and Silverlight. Code running on the Compact Framework is JIT-compiled and garbage-collected, although the Compact Framework collector isn’t generational like the ones in the desktop framework.

C.5.2. Silverlight

Silverlight ( is aimed at running applications either within browsers, or (as of Silverlight 3) in a sandboxed environment, usually originally installed from a browser. As such, it’s a natural competitor to Flash; it has the obvious advantage of allowing C# developers to write applications in a familiar language against a familiar library. Silverlight installs a streamlined CLR (called CoreCLR—see and class library—for example, the nongeneric collections aren’t supported, and neither is Windows Forms. The presentation layer of Silverlight is based on WPF, but they’re not identical. It has particularly strong support for media, with features such as deep zoom and adaptive video streaming.

Silverlight 1 was released in September 2007, although it was restricted to a mixture of XAML to construct the UI and JavaScript for logic. It wasn’t until Silverlight 2 was released in October 2008 that the full experience of delivering Silverlight applications built with C# became a reality. Some of the features from CoreCLR (side-by-side CLR hosting within a single process, and the declarative transparency security model) are now features in the desktop CLR for version 4.0. It also included an early version of the Dynamic Language Runtime.

Progress continued unabated, with Silverlight 3 being released in July 2009 with more controls, more video codecs, as well as offline and out-of-browser applications. The Silverlight team repeated the nine-month release cycle, releasing Silverlight 4 in the same week as .NET 4 with another long list of new features. Windows Phone 7 supported Silverlight 3 and some features of Silverlight 4, and then when the Windows Phone 7.1 SDK was released (to support the phone with a consumer-branded version of 7.5, just to add confusion), that supported more of Silverlight 4 again. Both Windows Phone 7.x versions used an evolution of the Compact Framework CLR.

Windows Phone 8 supports the Silverlight API for backward compatibility, but also supports the new Windows Phone Runtime API which is closer to the WinRT API used for Windows Store applications. Additionally, Windows Phone 8 uses a version of CoreCLR rather than the one from the Compact Framework.

Silverlight itself is now dead in terms of further development. While I’m sure many developers are still using it, there will be no new versions released. However, WinRT should feel very familiar to Silverlight developers. Microsoft has attempted to make the transition from Silverlight applications to Windows Store applications pretty smooth.

C.5.3. Micro Framework

The Micro Framework (see is a tiny implementation of .NET, designed to run on very constrained devices. It doesn’t support generics, it’s interpreted rather than JIT-compiled, and it ships with a limited set of classes, but it does include a presentation layer, built around WPF. In order to save space, you only need to deploy the parts of the framework you actually need—at its smallest, it can take up a mere 390 KB. Obviously, this is a somewhat niche area, but the ability to write managed code for embedded devices has great appeal. It won’t be suitable for all situations—it’s not a real-time system, for example—but where it’s applicable, it’s likely to dramatically improve developer productivity.

The release history hasn’t followed that of the desktop framework at all: it was first seen in the SPOT watch in 2004, but version 1.0 was released in 2006. Since then it has iterated several times in rapid succession. Version 4.0 of the Micro Framework shipped on November 19, 2009—and in a move that still delights and surprises me, the majority of this version was released open source under the Apache 2.0 license. Some libraries, such as the TCP/IP stack and cryptography implementations, are still closed for various reasons; these companion libraries can be downloaded in binary form for specific architectures.

C.5.4. Windows Runtime (WinRT)

WinRT isn’t another version of .NET—it’s a whole new Windows platform, introduced in Windows 8. It aims to provide a sandboxed environment on both x86 and ARM processor architectures, and supports multiple languages—primarily C# and VB via .NET, C++/CX (a new flavor of C++ specifically targeting WinRT), and JavaScript. It’s an unmanaged API, but it’s designed to integrate very closely with .NET, so that C# and VB.NET developers can really use the same APIs as C++/CX and JavaScript developers. There’s no need for a wrapper API to be built around it, as was the case for Win32 with Windows Forms. The API has been designed with asynchrony in mind right from the start; using asynchrony is the natural way of developing apps targeting WinRT.

As Windows 8 is a young operating system, we have yet to see how well this will pan out in the long run, and developers wanting to create apps to run on Windows 8 can still target the traditional desktop, but it’s clear that Microsoft believes that WinRT is an important way forward for client-side development. In particular, the Windows Phone API and the Windows Store API are likely to converge more and more closely in the future.

C.6. Summary

With so many versions of so many different components, it’s easy to get confused—and even easier to confuse someone else. As a final piece of advice (and I mean final—it’s hard to sneak anything deep and meaningful into an index), I recommend that you try to be as clear as possible on this topic when communicating with others. If you’re using anything other than the desktop framework, say so. If you’re going to quote a version number, specify exactly what you mean—“3.0” could mean using C# 2.0 and .NET 3.0, or it could mean using C# 3.0 and .NET 3.5. Aside from anything else, after you’ve read this book, you have absolutely no excuse for claiming you’re using “C# 3.5” or “C# 4.5” unless you’re deliberately trying to wind me up.