July 31, 2000 -- Microsoft's new vision of the Internet is a far cry from today's network of online content. Microsoft views the future Internet as a world of interrelated services that are developed by different individuals, written in different languages, deployed on different types of hardware, and hosted by different Internet operating systems.

The company's offering for this brave new world is the .Net platform. Actually, .Net is not a platform in the traditional sense; it is not a common hardware or software system. Instead, .Net is a collection of protocols that allow Internet applications to take advantage of disparate services running on different machines.

One direct result of Microsoft's new strategy is that the next version of Microsoft Visual Studio will feature retooled languages, modified explicitly to support the .Net platform. Java will be missing from the package, as Visual J++ is being discontinued. Not to worry, though; Microsoft will be introducing a new language, called C#, to fill the void. The company has assigned its best resources, including star language specialist Anders Hejlsberg, to C#'s development.

Suitably controversial: Anders Hejlsberg, the language architect

Given Hejlsberg's history, it's no surprise that Microsoft would entrust this endeavor to him. After all, C# will not be his first attempt to revolutionize the software-development landscape.

As chief architect at Borland, Hejlsberg secretly turned Turbo Pascal into an object-oriented application development language, complete with a truly visual environment and superb database-access features. Once touted as the "VB killer," Delphi has remained a cornerstone product for Borland (now Inprise/Borland).

When Microsoft hired Hejlsberg, luring him with a generous salary, stock options, and a large sign-on bonus, Borland sued for unfair recruiting practices. Borland also claimed -- providing few details to support the accusation -- that Hejlsberg was working on "Delphi for Java." This suit was eventually settled in Borland's favor; by that time, however, Microsoft had put Hejlsberg to work.

Hejlsberg beefed up Microsoft's Java offering; among other things, he artificially propelled its version number from 1.1 to 6.0 in one release in order to keep it current with the versioning of other Visual Studio languages. In fact, this leapfrogging of version numbers did not exaggerate the differences between 6.0 and its predecessor. Hejlsberg had added features that turned the language into a powerful Windows application-development platform. Additions included access to the Windows API; consequently, programs that took advantage of new features were not portable.

Hejlsberg's changes to Microsoft's offering prompted Sun to sue Microsoft for Java license violations. Instead of keeping the Java platform neutral, Sun claimed, Visual J++ language extensions locked developers into the Microsoft platform. Despite the fact that Microsoft's Visual J++ is arguably the best Java compiler, and that the company's virtual machine (the runtime module that executes Java bytecode) is one of the fastest available, Sun's suit has effectively prevented Microsoft from competing in the Java arena.

Microsoft has responded by pulling back from Java altogether, replacing it with a new cornerstone Internet platform -- .Net -- and a new banner language -- C#. Anders Hejlsberg is the natural choice to front the latter effort.

Justifying a new programming language

Some of the recent press concerning C# contends that developers will not accept yet another programming language. While it is true that several useful languages are already available to developers, there is room for one more -- provided it meets still-unfulfilled needs. A new language is, after all, just another tool that professionals can use to create software solutions. Let's examine the goals that Microsoft has set for C#, and the ways in which other languages to date have not met them.

Rapid application development: One of Microsoft's most significant goals for C# is support for RAD. Internet applications must be developed in Internet time; a new language must be easy to learn and debug, and must produce code that is easy to update. While Delphi and VB excel in these areas, C++ has not been quite as successful. The language itself is complex and difficult to master, and few useful C++ libraries provide simple interfaces. In addition, C++'s manual memory management and complex type-casting model make it difficult to debug.

Furthermore, as we will see below, C++ does not inherently protect against potential problems caused by version incompatibilities. Despite all the effort that Microsoft and Borland have put into the language, C++ is still not suitable for rapid application development.

Cross-platform deployment: Internet languages should, by definition, support cross-platform deployment. Because the Internet is a network of disparate systems, services must be deployed to a wide range of hardware and software. Furthermore, client-side software should be capable of running on several types of devices, including PDAs and cell phones. Such flexibility is a challenge for virtually all languages, with the exception of Java. VB in particular produces only Windows applications for Intel-based machines. Delphi, too, suffers the same restriction. Delphi for Linux will be available soon, but it does not yet provide support for Internet appliances. Neither VB nor Delphi meets the goal of cross-platform deployment.

Access to platform-native resources; According to Microsoft, developers demand access to platform-native resources. Such access is sometimes necessary for writing powerful targeted applications. Visual J++ 6.0 granted developers access to the Windows API, which Java in general does not allow. Instead, Java provides for cross-platform deployment by defining a lowest common denominator standard that every virtual machine implements. Java developers must write to this weaker standard instead of taking advantage of more powerful services offered only on certain platforms. Thus, Java fails to meet the goal of providing access to platform-native resources.

Support for the COM and .Net platforms: Microsoft has identified support for the COM and .Net platforms as C#'s most important goal. Naturally, no other language currently supports the .Net platform, as it is still under construction. Unlike .Net, COM has been around for quite some time, but it nevertheless lacks strong language support. Most languages, C++ and Delphi included, require that developers create an additional IDL declaration, a class factory, and special embellishments for each COM object they create.

Some language vendors have provided wizards that automate many common COM and OLE tasks, but these tools do not completely hide the complexity of COM. VB does successfully hide COM's complexity, but only by sacrificing power. VB doesn't only lack the power of an object-oriented language; it also fails to support low-level COM functionality -- multiple interfaces, aggregation, and custom marshaling, for example. In short, no existing language supports COM as comprehensively as C# does.

While these four goals are fairly lofty for a new language, Hejlsberg has drawn from the best of his experience in his efforts to make sure that C# achieves them. The result is a language that draws from Java and Delphi as much as, if not more than, it draws from C and C++. Note that the information that follows is based on the C# working spec, and may not accurately represent the final product release.

C# is a RAD environment

C# provides Java-style garbage collection: One of the most significant RAD features that C# provides is Java-style garbage collection. At arbitrary intervals during runtime, all unreferenced objects are automatically deleted. By relieving the developer of manual memory-management tasks, garbage collection makes program development easier and less prone to error. Automatic garbage collection, however, is time-consuming and unpredictable. C# therefore allows developers to disable garbage collection locally -- by marking code as unsafe -- in situations where realtime performance is required.

C# implements a Java- and Delphi-style value/reference-type system: To further support RAD, C# does away with the C/C++ pointer model in favor of a Java- and Delphi-style value/reference-type system. In this system, built-in types (integer, real, string, and so on), enumerations, and structures are all value types. The assignment and comparison operators copy and examine the values of these types of variables. Interfaces, classes, and delegates (described later) are all reference types. The assignment and comparison operators copy and examine the identity of the objects to which these types of variables refer.

This value/reference-type system is much simpler than the C++ pointer model. It makes for much easier object manipulation and eliminates many of the memory bugs that plague C and C++ programs.

C# interfaces are declared independently of classes: C# also supports a Java- and Delphi-like interface model, in which interfaces are declared independently of classes. This stands in contrast to the C++ model, in which interfaces are actually abstract base classes. Both interfaces and classes may inherit multiple interfaces. While classes may inherit one base class, interfaces cannot inherit classes at all. This model avoids C++'s multiple-inheritance problem, in which implementations in different base classes can conflict. The need for complex mechanisms such as virtual inheritance and explicit scoping is also thereby eliminated. C#'s simplified interface model helps speed application development.

Declaration and definition of class methods are combined: Another way that C# simplifies development is by combining the declaration and definition of class methods, much as Java does. C++ developers must maintain separate files for declarations (the header file) and definitions (the implementation file), complicating the software development process. Relieving the developer of one more chore, C# even automatically discovers relationships among source modules. Where C++ requires #include (and Delphi requires uses), C# needs no additional input to locate related source files.

C# uses method references, called delegates, instead of method pointers: C# uses method references to quickly connect objects and methods. Called delegates, these method references are similar to Delphi's procedural types. Hejlsberg introduced this same mechanism into Visual J++ 6.0, though it is not part of the standard Java specification. Method references are somewhat similar to C++ method pointers, but are far more elegant, safe, and useful.

A delegate is a reference type that holds a method's signature. An application can assign any method that matches this signature to a delegate variable. When this delegate variable is invoked, the associated method is called. Unlike Delphi procedure types, C# delegates automatically support multicasting. An application can assign many methods to one delegate variable; when the variable is invoked, all methods are called.

C# uses Java's mechanism for simple thread synchronization: To implement thread synchronization in C#, a developer simply marks the blocks of code that are critical. Where a Java developer would use the synchronized keyword, a C# developer uses lock. A hidden mutex wraps the marked block, allowing only one thread to execute the code at any given time. Differing keywords aside, this mechanism is the same in both C# and Java. Because threading is one of the most error-prone of all programming tasks, any feature that simplifies synchronization aids in rapid application development.

A developer of a derived C# class must explicitly mark a method override with the keyword override, just as he or she does when working with Delphi. If a derived class includes an unmarked method that has the same name as a virtual method in the base class, the compiler cannot unambiguously discern the author's intent.

On the one hand, a naming conflict could very well be accidental; this is especially likely if the base class and derived class were implemented independently by different programmers, perhaps working for different companies. In such a case, the compiler will issue a warning and treat the derived class method as a new declaration, not as an override.

If, on the other hand, the developer has consciously chosen to use a name for a new method in a derived class that is the same as the name of a virtual method in a base class, he or she can include the new keyword to prevent a warning from the compiler.