Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.69 MB, 424 trang )
A brief history of C# (and related technologies)
19
Java is reasonably portable, despite the “write once, debug everywhere” skit on Sun’s
catchphrase of “write once, run anywhere.” The idea of letting coders develop enterprise Java applications on Windows with friendly IDEs and then deploy (without even
recompiling) to powerful Unix servers was a compelling proposition—and clearly
something of a threat to Microsoft.
Microsoft created their own Java Virtual Machine (JVM), which had reasonable
performance and a very fast startup time, and even released an IDE for it, named J++.
However, they introduced incompatible extensions into their platform, and Sun sued
Microsoft for violating licensing terms, starting a very long (and frankly tedious) legal
battle. The main impact of this legal battle was felt long before the case was concluded—while the rest of the world moved on to Java 1.2 and beyond, Microsoft’s version of Java stayed at 1.1, which made it effectively obsolete pretty rapidly. It was clear
that whatever Microsoft’s vision of the future was, Java itself was unlikely to be a major
part of it.
In the same period, Microsoft’s Active Server Pages (ASP) gained popularity too.
After an initial launch in December 1996, two further versions were released in 1997
and 2000. ASP made dynamic web development much simpler for developers on
Microsoft servers, and eventually third parties ported it to non-Windows platforms.
Despite being a great step forward in the Windows world, ASP didn’t tend to promote
the separation of presentation logic, business logic, and data persistence, which most
of the vast array of Java web frameworks encouraged.
1.2.2
5
C# and .NET are born
C# and .NET were properly unveiled at the Professional Developers Conference
(PDC) in July 2000, although some elements had been preannounced before then,
and there had been talk about the same technologies under different names
(including COOL, COM3, and Lightning) for a long time. Not that Microsoft hadn’t
been busy with other things, of course—that year also saw both Windows Me and
Windows 2000 being released, with the latter being wildly successful compared with
the former.
Microsoft didn’t “go it alone” with C# and .NET, and indeed when the specifications for C# and the Common Language Infrastructure (CLI) were submitted to
ECMA (an international standards body), they were co-sponsored by Hewlett-Packard
and Intel along with Microsoft. ECMA ratified the specification (with some modifications), and later versions of C# and the CLI have gone through the same process. C#
and Java are “open” in different ways, with Microsoft favoring the standardization
path and Sun gradually open sourcing Java and allowing or even encouraging other
Java runtime environments. There are alternative CLI and C# implementations, the
most visible being the Mono project,5 but they don’t generally implement the whole
of what we think of as the .NET Framework. Commercial reliance on and support
http://www.mono-project.com
20
CHAPTER 1
The changing face of C# development
of non-Microsoft implementations is small, outside of Novell, which sponsors the
Mono project.
Although C# and .NET weren’t released until 2002 (along with Visual Studio
.NET 2002), betas were available long before then, and by the time everything was official, C# was already a popular language. ASP.NET was launched as part of .NET 1.0, and
it was clear that Microsoft had no plans to do anything more with either “ASP Classic”
or “VB Classic”—much to the annoyance of many VB6 developers. While VB.NET looks
similar to VB6, there are enough differences to make the transition a nontrivial one—
not least of which is learning the .NET Framework. Many developers have decided to go
straight from VB6 to C#, for various reasons.
1.2.3
Minor updates with .NET 1.1 and the first major step: .NET 2.0
As is often the case, the 1.0 release was fairly quickly followed by .NET 1.1, which
launched with Visual Studio .NET 2003 and included C# 1.2. There were few significant changes to either the language or the framework libraries—in a sense, it was
more of a service pack than a truly new release. Despite the small number of changes,
it’s rare to see anyone using .NET 1.0 at the time of this writing, although 1.1 is still
very much alive and kicking, partly due to the OS requirements of 2.0.
While Microsoft was busy bringing its new platform to the world, Sun (and
its other significant partners, including IBM) hadn’t left Java stagnating.
ion is
Imitat erest
Not quite, anyway. Java 1.5 (Java 5 for the marketing folk among you) was
nc
the si
launched in September 2004, with easily the largest set of language
m of
for
y
enhancements in any Java release, including generics, enums (supported
flatter
in a very cool way—far more object-oriented than the “named numbers”
that C# provides), an enhanced for loop (foreach to you and me), annotations (read: attributes), “varargs” (broadly equivalent to parameter
arrays of C#—the params modifier), and automatic boxing/unboxing. It would be foolish to suggest that all of these enhancements were due to C# having taken off (after all,
putting generics into the language had been talked about since 1997), but it’s also
worth acknowledging the competition for the mindshare of developers. For Sun,
Microsoft, and other players, it’s not just about coming up with a great language: it’s
about persuading developers to write software for their platform.
C# and Java have both been cautious when it comes to introducing powerful features such as templates and macros from C++. Every new feature has to earn its place
in the language in terms of not just power, but also ease of use and readability—and
sometimes that can take time. For example, both Java and C# shipped without anything like C++ templates to start with, and then worked out ways of providing much of
their value with as few risks and drawbacks as possible. We’ll see in chapter 3 that
although Java and C# generics look quite similar on the most superficial level, they
differ significantly under the surface.
A brief history of C# (and related technologies)
NOTE
21
The pioneering role of Microsoft Research—Microsoft Research is responsible
for some of the new directions for .NET and C#. They published a paper
on .NET generics as early as May 2001 (yes, even before .NET 1.0 had
been released!) and worked on an extension called Cω (pronounced C
omega), which included—among other things—some of the ideas which
later formed LINQ. Another C# extension, Spec#, adds contracts to C#,
allowing the compiler to do more verification automatically.6 We will
have to wait and see whether any or all of the ideas of Spec# eventually
become part of C# itself.
C# 2 was released in November 2005, as part of .NET 2.0 and alongside Visual Studio 2005 and VB8. Visual Studio became more productive to work with as an IDE—particularly now that refactoring was finally included—and the significant improvements
to both the language and the platform were warmly welcomed by most developers.
As a sign of just how quickly the world is moving on—and of how long it takes to
actually bring a product to market—it’s worth noting that the first announcements
about C# 3 were made at the PDC in September 2005, which was two months before
C# 2 was released. The sad part is that while it seems to take two years to bring a product from announcement to market, it appears that the industry takes another year or
two—at least—to start widely embracing it. As mentioned earlier, many companies are
only now transitioning from .NET 1.1 to 2.0. We can only hope that it will be a shorter
path to widespread adoption of .NET 3.0 and 3.5. (C# 3 comes with .NET 3.5, although
you can use many C# 3 features while still targeting .NET 2.0. I’ll talk about the version
numbers shortly.)
One of the reasons .NET 2.0 took so long to come out is that it was being embedded within SQL Server 2005, with the obvious robustness and reliability concerns that
go hand in hand with such a system. This allows .NET code to execute right inside the
database, with potential for much richer logic to sit so close to the data. Database folk
tend to be rather cautious, and only time will tell how widely this ability is used—but
it’s a powerful tool to have available if you find you need it.
1.2.4
6
“Next generation” products
In November 2006 (a year after .NET 2.0 was released), Microsoft launched Windows
Vista, Office 2007, and Exchange Server 2007. This included launching .NET 3.0,
which comes preinstalled on Vista. Over time, this is likely to aid adoption of .NET client applications for two reasons. First, the old “.NET isn’t installed on all computers”
objection will become less relevant—you can safely assume that if the user is running
Vista, they’ll be able to run a .NET application. Second, Windows Presentation Foundation (WPF) is now the rich client platform of choice for developers in Microsoft’s
view—and it’s only available from .NET.
http://research.microsoft.com/specsharp/
22
CHAPTER 1
The changing face of C# development
Again, while Microsoft was busy with Vista and other products, the rest of the world
was innovating too. Lightweight frameworks have been gaining momentum, and
Object Relational Mapping (ORM) now has a significant developer mindshare, partly
due to high-quality free frameworks such as Hibernate. The SQL aspect of LINQ is
much more than just the querying side we’ve seen so far, and marks a more definite
step from Microsoft than its previous lukewarm ventures into this area, such as
ObjectSpaces. Only time will tell whether LINQ to SQL or perhaps its cousin the
ADO.NET Entity Framework hits the elusive sweet spot of making database access truly
simple—they’re certainly very promising.
Visual Studio 2008 was released in November 2007, including .NET 3.5, C# 3, and
VB9. It contains built-in support for many features that were previously only available as
extensions to Visual Studio 2005, as well as the new language and framework features.
Continuing the trend from Visual Studio 2005, a free Express edition is available for
each language. With the ability to target multiple versions of the .NET Framework and
only minimal solution and project changes when migrating existing code, there is little
reason not to upgrade to Visual Studio 2008—I expect its adoption rate to be far faster
than that of Visual Studio 2005.
Dynamic languages have become increasingly important, with many options vying
for developers’ attention. Ruby—and particularly the Ruby on Rails framework—has
had a large impact (with ports for Java and .NET), and other projects such as Groovy on
the Java platform and IronRuby and IronPython on .NET are gaining support. As part
of Silverlight 2.0, Microsoft will release the Dynamic Language Runtime (DLR), which
is a layer on top of the CLR to make it more amenable to dynamic languages. Silverlight
is part of another battleground, but this time for rich Internet applications (RIAs),
where Microsoft is competing with Adobe Flex and Sun’s JavaFX. Silverlight 1.0 was
released in September 2007, but this version was based on JavaScript. At the time of this
writing, many developers are currently awaiting 1.1, which will ship with a “mini-CLR”
and cater for multiple platforms.
1.2.5
Historical perspective and the fight for developer support
It’s hard to describe all of these strands interweaving through history and yet keep a
bird’s-eye view of the period. Figure 1.5 shows a collection of timelines with some of
the major milestones described earlier, within different technological areas. The list is
not comprehensive, of course, but it gives some indication of which product versions
were competing at different times.
There are many ways to look at technological histories, and many untold stories
influencing events behind the scenes. It’s possible that this retrospective overemphasizes the influence of Java on the development of .NET and C#, and that may
well partly be due to my mixed allegiances to both technologies. However, it seems
to me that the large wars for developer support are taking place among the following camps.
23
A brief history of C# (and related technologies)
Java
.NET
Other MS
Others
JDK 1.0
VB6
ASP 1.0
1996
1996
Ruby 1.0
JDK 1.1
1997
1997
ASP 2.0
Windows 98
PHP 3.0
1998
1998
J2SE 1.2
1999
1999
J2EE 1.2
Windows 2000
J2SE 1.3
2000
2001
.NET
unveiled
PHP 4.0
2000
ASP 3.0
J2SE 1.4
.NET 1.0,
C# 1.0,
VS.NET 2002
Windows XP
2002
.NET 1.1,
C# 1.2,
VS.NET 2003
2003
Windows
Server 2003
Mono
announced
2001
Hibernate 1.0
J2EE 1.3
2002
Hibernate 2.0
2003
J2EE 1.4
2004
Mono 1.0,
PHP 5.0
J2SE 5.0
2004
Hibernate 3.0
2005
.NET 2.0,
C# 2.0,
VS 2005
SQL Server
2005
.NET 3.0
Windows Vista,
Exchange 2007
Ruby On Rails
1.0
2005
Java EE 5
2006
J2SE 6.0
2007
Figure 1.5
.NET 3.5,
C# 3.0,
VS 2008
Silverlight
1.0
2006
Groovy 1.0
2007
Ruby On Rails
2.0
Timeline of releases for C#, .NET, and related technologies
24
CHAPTER 1
■
■
■
■
■
The changing face of C# development
Native code (primarily C and C++) developers, who will have to be convinced
about the reliability and performance of managed code before changing their
habits. C++/CLI is the obvious way of dipping a toe in the water here, but its
popularity may not be all that Microsoft had hoped for.
VB6 developers who may have antipathy toward Microsoft for abandoning their
preferred platform, but will need to decide which way to jump sooner or later—
and .NET is the most obvious choice for most people at this stage. Some may
cross straight to C#, with others making the smaller move to VB.NET.
Scripting and dynamic language developers who value the immediacy of
changes. Familiar languages running on managed platforms can act as Trojan
horses here, encouraging developers to learn the associated frameworks for use
in their dynamic code, which then lowers the barrier to entry for learning the
traditional object-oriented languages for the relevant platform. The IronPython
programmer of today may well become the C# programmer of tomorrow.
“Traditional” managed developers, primarily writing C#, VB.NET, or Java. Here
the war is not about whether or not running under some sort of managed environment is a good thing, but which managed environment to use. The battlegrounds are primarily in tools, portability, performance, and libraries, all of
which have come on in leaps and bounds. Competition between different .NET
languages is partly internal to Microsoft, with each team wanting its own language to have the best support—and features developed primarily for one
language can often be used by another in the fullness of time.
Web developers who have already had to move from static HTML, to dynamically generated content, to a nicer user experience with Ajax. Now the age of
RIAs is upon us, with three very significant contenders in Microsoft, Adobe, and
Sun. At the time of this writing, it’s too early to tell whether there will be a clear
winner here or whether the three can all garner enough support to make them
viable for a long time to come. Although it’s possible to use a .NET-based RIA
solution with a Java-based server to some extent, the development process is significantly easier when technologies are aligned, so capturing the market here is
important for all parties.
One thing is clear from all of this—it’s a good time to be a developer. Companies are
investing a lot of time and money in making software development a fun and profitable industry to be in. Given the changes we’ve seen over the last decade or so, it’s difficult to predict what programming will look like in another decade, but it’ll be a
fantastic journey getting there.
I mentioned earlier that C# 3 is effectively part of .NET 3.5. It’s worth taking a bit of
time to look at the different aspects that together make up .NET.
1.3
The .NET platform
When it was originally introduced, “.NET” was used as a catchall term for a vast range
of technologies coming from Microsoft. For instance, Windows Live ID was called
The .NET platform
25
.NET Passport despite there being no clear relationship between that and what we currently know as .NET. Fortunately things have calmed down somewhat since then. In
this section we’ll look at the various parts of .NET (at least the ones we’re interested
in) and how they have been separately versioned.
1.3.1
Distinguishing between language, runtime, and libraries
In several places in this book, I’ll refer to three different kinds of features: features of
C# as a language, features of the runtime that provides the “engine” if you will, and features of the .NET framework libraries. In particular, this book is heavily focused on the
language of C#, only explaining runtime and framework features when they relate to
features of C# itself. This only makes sense if there is a clear distinction between the
three. Often features will overlap, but it’s important to understand the principle of
the matter.
LANGUAGE
The language of C# is defined by its specification, which describes the format of C#
source code, including both syntax and behavior. It does not describe the platform that
the compiler output will run on, beyond a few key points at which the two interact. For
instance, the C# language requires a type called System.IDisposable, which contains
a method called Dispose. These are required in order to define the using statement.
Likewise, the platform needs to be able to support (in one form or other) both value
types and reference types, along with garbage collection.
In theory, any platform that supports the required features could have a C# compiler
targeting it. For example, a C# compiler could legitimately produce output in a form
other than the Intermediate Language (IL), which is the typical output at the time of
this writing. A runtime could legitimately interpret the output of a C# compiler rather
than JIT-compiling it. In practice, although interpreting IL is possible (and indeed supported by Mono), we are unlikely to see widespread use of C# on platforms that are very
different from .NET.
RUNTIME
The runtime aspect of the .NET platform is the relatively small amount of code that is
responsible for making sure that programs written in IL execute according to the CLI
specification, partitions I to III. The runtime part of the CLI is called the Common
Language Runtime (CLR). When I refer to the CLR in the rest of the book, I mean
Microsoft’s implementation.
Some elements of language never appear at the runtime level, but others cross the
divide. For instance, enumerators aren’t defined at a runtime level, and neither is any
particular meaning attached to the IDisposable interface—but arrays and delegates
are important to the runtime.
FRAMEWORK LIBRARIES
Libraries provide code that is available to our programs. The framework libraries in
.NET are largely built as IL themselves, with native code used only where necessary. This
is a mark of the strength of the runtime: your own code isn’t expected to be a secondclass citizen—it can provide the same kind of power and performance as the libraries
26
CHAPTER 1
The changing face of C# development
it utilizes. The amount of code in the library is much larger than that of the runtime,
in the same way that there’s much more to a car than the engine.
The .NET libraries are partially standardized. Partition IV of the CLI specification
provides a number of different profiles (compact and kernel) and libraries. Partition IV
comes in two parts—a general textual description of the libraries, including which
libraries are required within which profiles, and another part containing the details of
the libraries themselves in XML format. This is the same form of documentation produced when you use XML comments within C#.
There is much within .NET that is not within the base libraries. If you write a program that only uses libraries from the specification, and only uses them correctly, you
should find your code works flawlessly on any implementation—Mono, .NET, or anything else. In practice, almost any program of any size will use libraries that aren’t
standardized—Windows Forms or ASP.NET, for instance. The Mono project has its
own libraries that are not part of .NET as well, of course, such as GTK#, in addition to
implementing many of the nonstandardized libraries.
The term .NET refers to the combination of the runtime and libraries provided by
Microsoft, and it also includes compilers for C# and VB.NET. It can be seen as a whole
development platform built on top of Windows.
Now that we know what term means what, we can look at different versions available of each. The subject of the version numbers chosen by Microsoft and what’s in
which version is a slightly convoluted one, but it’s important that we all agree on what
we mean when we talk about a particular version.
1.3.2
Untangling version number chaos
A newcomer to the industry might think that coming up with version numbers would
be easy. You start with 1, then move on to 2, then 3 in a logical progression, right? If only
that were the case… Software products and projects of all natures like to keep minor
version changes distinct from major ones, and then there are patch levels, service packs,
build numbers, and so forth. In addition, there are the codenames, which are widely used
and then abandoned, much to the frustration of “bleeding edge” book authors and
publishers. Fortunately from the point of view of C# as a language we can make life reasonably straightforward.
NOTE
Keeping it simple: C# 1, C# 2, and C# 3—Throughout this book, I’ll refer to
C# versions as just 1, 2, and 3. There’s little point in distinguishing
between the two 1.x versions, and no point in adding a cumbersome
extra “.0” every time I refer to the different versions—which of course I’ll
be doing quite a lot.
We don’t just need to keep track of the language, unfortunately. There are five things
we’re interested in, when it comes to versioning.
■
■
■
The .NET Framework
Framework libraries
The CLR
27
The .NET platform
■
■
C# (the version of the compiler that comes with the framework)
Visual Studio—version number and codename
Just for kicks, we’ll throw in the Visual Basic numbering and naming too. (Visual Studio is abbreviated to VS and Visual Basic is abbreviated to VB for reasons of space.)
Table 1.1 shows the different version numbers.
Table 1.1
.NET
Cross-reference table for versions of different products and technologies
Framework
libraries (max)
CLR
C#
Visual Studio
Visual Basic
1.0
1.0
1.0
1.0
VS .NET 2002 (no codename)
VB.NET 7.0
1.1
1.1
1.1
1.2a
VS .NET 2003 (Everett)
VB.NET 7.1
2.0
2.0
2.0
2.0
VS 2005 (Whidbey)
VB 8.0
3.0
3.0
2.0
2.0
VS 2005 (extension previews),
VS 2008 (full support)
VB 8.0
3.5
3.5
2.0
3.0
VS 2008 (Orcas)
VB 9.0
a. I’ve no idea why this isn’t 1.1. I only discovered that it was 1.2 while researching this book. That’s the
numbering according to Microsoft’s version of the specification, at least. I decided not to confuse matters
further by also including the ECMA-334 edition number here, although that’s another story in its own right.
Note how both Visual Studio and Visual Basic lost the “.NET” moniker between 2003
and 2005, indicating Microsoft’s emphasis on this being the tool for Windows development, as far as they’re concerned.
As you can see, so far the version of the overall framework has followed the libraries exactly. However, it would be possible for a new version of the CLR with more capabilities to still be released with the existing libraries, so we could (for instance) have
.NET 4.0 with libraries from 3.5, a CLR 3.0, and a C# 3 compiler. Let’s hope it doesn’t
come to that. As it is, Microsoft has already confounded developers somewhat with the
last two lines of the table.
.NET 3.0 is really just the addition of four libraries: Windows Presentation Foundation (WPF), Windows Communication Foundation (WCF), Windows Workflow
Foundation (WF7), and Windows CardSpace. None of the existing library classes
were changed, and neither was the CLR, nor any of the languages targeting the CLR,
so creating a whole new major version number for this feels a bit over the top.
Next comes .NET 3.5. This time, along with completely new classes (notably LINQ)
there are many enhancements to the base class libraries (BCL—types within the
namespaces such as System, System.IO; the core of the framework libraries). There’s a
new version of C#, without which this book would be considerably shorter, and a new version of Visual Studio to support that and VB 9.0. Apparently all of that isn’t worth a major
version number change, though. There are service packs for both .NET 2.0 and 3.0, and
7
Not WWF due to wrestling and wildlife conflicts.
28
CHAPTER 1
The changing face of C# development
both service packs ship with Visual Studio 2008—so while you can target .NET 2.0
and 3.0 with the latest and greatest IDE (as well as 3.5, of course) you should be aware
that what you’ll really be compiling and running against is 2.0SP1, 3.0SP1 or 3.5.
OK, rant over. It’s only version numbers, after all—but it is important to understand what each version means, if for no other reason than communication. If someone says they’re using “3.0” you need to check whether they mean C# 3 or .NET 3.0.
If all this talk of history and versioning is making you want to get back onto the
familiar ground of actual programming, don’t worry—we’re nearly there. Indeed, if
you fancy writing some code right now, the next section invites you to do just that, as I
introduce the style I’ll be using for most of the examples in this book.
1.4
Fully functional code in snippet form
One of the challenges when writing a book about a computer language (other than
scripting languages) is that complete programs—ones that the reader can compile
and run with no source code other than what’s presented—get pretty long pretty
quickly. I wanted to get around this, to provide you with code that you could easily
type in and experiment with: I believe that actually trying something is a much better
way of learning about it than just reading.
The solution I’ve come up with isn’t applicable to all situations, but it will serve us
well for most of the example code. It would be awful to use for “real” development,
but it’s specifically tailored to the context we’re working in: presenting and playing
with code that can be compiled and run with the minimal amount of fuss. That’s not
to say you should only use it for experimentation when reading this book—I’ve found
it useful as a general way of testing the behavior of small pieces of code.
1.4.1
Snippets and their expansions
With the right assembly references and the right using directives, you can accomplish
quite a lot in a fairly short amount of C# code—but the killer is the fluff involved in writing those using directives, then declaring a class, then declaring a Main method before
you’ve even written the first line of useful code. My examples are mostly in the form of
snippets, which ignore the fluff that gets in the way of simple programs, concentrating
on the important part. So, for example, suppose I presented the snippet in listing 1.18.
Listing 1.18 The first snippet, which simply displays two words on separate lines
foreach (string x in new string[] {"Hello", "There"})
{
Console.WriteLine (x);
}
This code clearly won’t compile on its own—there’s no class declaration, for a start. The
code from listing 1.18 corresponds to the full program shown in listing 1.19.
Listing 1.19 Expanded form of listing 1.18, creating a complete program
using System;
public class Snippet
Fully functional code in snippet form
29
{
[STAThread]
static void Main(string[] args)
{
foreach (string x in new string[] {"Hello", "There"})
{
Console.WriteLine (x);
}
}
}
Occasionally extra methods or even types are required, with a bit of code in the Main
method to access them. I indicate this by listing the non-Main code, then an ellipsis
(...) and then the Main code. So the code in listing 1.20 would turn into listing 1.21.
Listing 1.20 A code snippet with an extra method, called within the Main method
static string[] GetGreetingWords()
{
return new string[] {"Hello", "There"};
}
...
foreach (string x in GetGreetingWords())
{
Console.WriteLine (x);
}
Listing 1.21 Expanded form of listing 1.20
using System;
public class Snippet
{
static string[] GetGreetingWords()
{
return new string[] {"Hello", "There"};
}
[STAThread]
static void Main(string[] args)
{
foreach (string x in GetGreetingWords())
{
Console.WriteLine (x);
}
}
}
Types declared in snippets will be nested within the Snippet class, but that’s very
rarely a problem.
Now that we understand what snippets are and what they look like when they’re
expanded, let’s make them a bit more user friendly.