oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

News -- C# is Pronounced 'See Sharp'

by Arthur Griffith

Among the new technologies announced by Microsoft in June, and scheduled to debut at the Microsoft Professional Developer's Conference (PDC), is a new programming language called C#. C# (pronounced "See Sharp") is scheduled to be included with the next release of Microsoft's Visual Studio .NET programming environment. Modules written in C# will be compatible with those written in Visual C++ and Visual Basic, allowing true cross-language development on Microsoft .NET platforms for the first time. Early beta testers have had access to a command line version for several weeks. C# is best described as a response to the productivity needs of .NET web application and services developers in the same way that Visual Basic responded to the needs of Windows Developers in the 90s.

Modern programming languages are not hatched in a vacuum; they are created out of the experience and knowledge of their designers. And, the more people involved in a design, the broader the base of languages and experience from which to draw. It is also inevitable that any new language will rely heavily on the designs of previously successful languages.

Microsoft says that the C# language definition has been primarily derived from C and C++, and many elements of the language reflect that. C# is broader than Java in what its designers chose to inherit from C++ (such as structs), and it also adds new features of its own (such as source code versioning).

But C# is more like Java than anything else, in spite of Microsoft's silence on the subject. This is to be expected, I suppose, given the recent success of the latter and the gains in productivity over C++ that have been reported by the companies that use it. As for the politics involved, I will leave that to others. I want to talk about the language itself.

To help make sense out of all this, I have broken down the features of C# into those that are distinctly Java-like, those that have derived from standard C and C++, and those that are brand new in C#. As you will see, however, many of the features that C# has derived from these languages have taken on a C# cast of their own. This list is not meant to be an exhaustive treatment of C#, but it should give you a pretty good idea of its structure.

C# Features Derived From Java

  • Classes: Classes in C# are declared very much as they are in Java. This makes sense because experience has taught us that the Java model works very well. The Java keyword import has been replaced by using, which performs the same basic function. The point at which a class begins execution is the static method Main(). The following Hello World program demonstrates the basic form:

    using System;
    class Hello {
    	static void Main() {
    		Console.WriteLine("Hello, world");

    In this example, the name System refers to a namespace that contains a set of basic C# utility classes. The namespace contains the Console class, which is used in this example to output a string.

  • Classes can be abstract and final: A class that is declared as abstract cannot be instantiated; it can only be used as a base class. The C# keyword lock is like the Java keyword final, which declares a class to be non-abstract, but it also cannot be used as the base of another class.

  • Interfaces: Just as in Java, an interface is an abstract definition of a collection of methods. When class or struct implements an interface, it must implement all of the methods defined in the interface. A single class can implement a number of interfaces. There may be some subtle differences that surface later, but this feature appears to be unchanged from the one in Java.

  • Boolean operations: Conditional expressions result in the bool data type, which is a distinct type in the language. There is no direct conversion between bool and any other data type. The Boolean constants true and false are keywords in the language.

  • Errors: As in Java, throwing and catching exception objects manage error handling.

  • Memory management: There is automatic garbage collection, which is provided by the underlying .NET framework.

C# Features Derived From C and C++

  • Compilation: Programs compile directly into the standard binary executable form. If the previous Hello World program were to be stored in a text file named Hello.cs, it could be compiled into an executable named Hello.exe.

  • Structs: A C# struct is like a C++ struct in that it can contain both data declarations and methods. However, unlike C++, structs are distinct from classes and do not support inheritance. However, like Java, a struct can implement interfaces.

  • Preprocessor: There are preprocessor directives for conditional compilation, warnings, errors, and line control. The preprocessing directives available are:

        #define <symbol>
        #undef <symbol>
        #if <symbol>
        #elif <symbol>
    #warning <message> #error <message> #line <number> [<name>]

    There is no #include directive. There is no assigning of values to symbols on the #define statement, so there is no source code substitution--the symbols are only for use on the #if and #elif directives. The number (and optional name) on the #line directive modifies the line number and source file name reported by #warning and #error.

  • Operator overloading: Some operators can be overloaded, and some cannot. In particular, none of the assignment operators can be overloaded. The overloadable unary operators are:

    +  -  !  ~  ++  --  true  false

    And the overloadable binary operators are:

    +  -  *  /  %  &  |  ^  <<  >>  ==  !=  >  <  >=  <= 

Features Unique to C#

  • Declarations in the namespace: When you create a program, you create one or more classes within a namespace. In this same namespace (outside of a class) it is also possible to declare interfaces, enums, and structs. The using keyword must be employed to address the contents of other namespaces.

  • The fundamental data types: There are a wider variety of data types than found in C, C++, or Java. The types are bool, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, and decimal. Like Java, all of the types are of a fixed size. Like C and C++, there are both signed and unsigned versions of each. Like Java, a char contains a 16-bit Unicode character. New with C# is the decimal data type, for monetary data, that can contain up to 28 significant base 10 digits.

  • The two fundamental classes: A class named object is the base class of all other classes. A class named string is as much a part of the language as object. Being a part of the language makes is possible for the compiler to use it--whenever you code a quoted string in your program, the compiler creates a string object to hold it.

  • Assembly: An assembly is a collection of compiled classes, and possibly other language elements that are combined in a single file for execution. If it is a program, it has the file extension EXE. If it is a library, it has the file extension DLL.

  • Attributes: Each member of a class has an access attribute of public, protected, internal, protected internal, or private.

    • public: accessible to all code.
    • protected: accessible only from derived classes.
    • internal: accessible only from within the assembly;
    • protected internal: accessible only from derived classes within the assembly.
    • private: accessible only from the class itself.
  • Argument passing: Methods can be declared to accept a variable number of arguments. The default is to pass fundamental data types by value. The ref keyword can be used to force an argument to be passed by reference, which allows the argument to accept a return value. The out keyword also causes a pass by reference, except no initial value is expected.

  • Virtual methods and overriding: Before a method in a base class can be overridden, it must be declared as virtual. The method in the subclass that is the overriding method must be declared with the keyword override. This will both prevent accidental method overriding and document which methods are overriding methods in the superclass. It is a welcome feature that is bound to improve the readability and ease of maintenance of C# modules.

  • Properties: A COM object has properties, and because every C# class can be used as a COM object, C# allows property declarations to be made inside any class. Inside a C# class, each property is given a name and a data type.set accessor and get accessor keywords are used to declare the code to be executed when a property is read or updated, if permitted. The following example is a class that has a Caption property:

  • public class Button: Control {
    	private string caption;
    	public string Caption {
    		get {
    			return caption;
    		set {
    			caption = value;

    The property name can be addressed externally in an assignment statement as if it were a field, like this:

    Button b = new Button();
    b.Caption = "ABC";
    string s = b.Caption;
    b.Caption += "DEF"

    Assigning a value to b.Caption calls the set method. Assigning a value from b.Caption calls the get method. The += operation calls both get and set. Conceptually, a property addresses the contents of a single field in the class, but an accessor can be as complicated as any method.

  • Indexer: An indexer is similar to a property except that, instead of a property name, an indexing value inside square brackets (like an array subscript) is used to anonymously address a member of a class.

  • public class ListBox: Control {
    private string[] items;
    	public string this[int index] {
    		get {
    			return items[index];
    		set {
    			items[index] = value;

    The iterator can be used to anonymously address members of the internal arrays of strings like this:

    ListBox listBox = ...;
    listBox[0] = "hello";
  • Delegates and callbacks: A delegate object contains information required to call a specific method of a specific object. Think of it as a smart method pointer. The delegate can be passed to another location, and accessed to make a type-safe call to the represented method. A callback method is an example of a delegate. The event keyword is used in the declaration of methods that are to be the delegates called when an event occurs.

  • Versioning: C# allows developers to maintain multiple versions of classes in binary form by placing them in different namespaces. This allows both old and new versions of software to run simultaneously. Along with this binary versioning, there will be the built-in capability to maintain and manage multiple versions of the source code.

  • Checked and unchecked evaluation: A checked expression is one that will throw an exception if overflow occurs during evaluation. An unchecked expression is one that will not throw an exception. The keywords checked and unchecked can be used to explicitly specify how the evaluation is to be done:

    int j = checked(a * b);	
    int k = unchecked(a * b);
  • Explicit and implicit conversions: Like Java, C# allows for implicit conversion of the fundamental data types as long as there is no possible loss of data (such as assigning a byte to an int), but an explicit cast must be made if there is possible loss of data (such as assigning an int to a byte). C# extends this capability to other program elements by allowing the programmer to define both explicit and implicit conversions. For example, the following Digit struct can be implicitly assigned to a byte, but must be explicitly cast to be assigned to another Digit:

  • public struct Digit {
    	byte value;
    	public Digit(byte value) {
    		if(value < 0 || value > 9)
    			throw new ArgumentException();
    		this.value = value;
    	public static implicit operator byte(Digit d) {
    		return d.value;
    	public static explicit operator Digit(byte b) {
    		return new Digit(b);
  • Externally implemented methods: Methods in a class can be implemented externally. In the following example, the static method RemoveDirectory is implemented in the library named kernel32.dll:

  • class Path {
    	[DllImport("kernel32", setLastError=true)]
    	static extern bool RemoveDirectory(string name);
  • Iteration through the members of a collection: A foreach statement can be used to execute a block of code once for each member of a list or an array. The following example executes the loop in the WriteList() method once for each member of the ArrayList:

    using System;
    using System.Collections;
    class Test {
    	static void WriteList(ArrayList list) {
    		foreach(object o in list)
    	static void Main() {
    		ArrayList list = new ArrayList();
    		for(int i = 0; i < 10; i++)


Any experienced Windows programmer is certain to find something to like in the list of C# language features. I particularly like the properties and the indexing capabilities of the language. I also like the concept of delegates because whenever I am developing code I feel alienated from the event process. The delegates could make it all more accessible.

There are some features in the list that were new with Java, but will undoubtedly be with us in computer languages from now on. The fixed-size data types (that is, a 32-bit int and a 64-bit long) lend themselves not only to great portability, but they simplify programming because you always know exactly what you're dealing with. And, of course, once you have worked with a language that uses automatic garbage collection, you will forever miss it when you don't have it. In the same way, I think some of the new features of C#, such as indexers, properties and versioning, will be successful enough to become part of programming languages of the future.

While the language described in the released C# specification and other press materials seems complete, Microsoft has so far remained silent on the underlying framework and base class libraries needed to make C# the equal of C++ or Visual Basic. Windows programmers have been asking for years for a clean object oriented interface to the Windows 32 APIs and many of the newer facilities that have been added to the Windows 32 operating system, such as the XML parser and COM+ services. A preview of what might be in store can be seen in the WFC class libraries released with the Visual J++ tool, now largely forgotten as a result of the Sun and Microsoft court battles. Perhaps we shall hear more this coming week at the PDC.

On the whole, however, I like the design of C#. If a good implementation follows, then I think .NET platform developers will find themselves gravitating to this new tool as they work their way through lengthening lists of programming tasks in the brave new world of n-tier web application programming.

Arthur Griffith is a former programmer and compiler writer.