The facts

C# is a computer programming language announced by Microsoft in July 2000, and launched circa 2001-2002.

C# (pronounced see-sharp) is a object-oriented, garbage collected language that runs on the .NET virtual machine (called the Common Language Runtime or CLR).

Much like Java, it has single inheritance of objects rooted at a single base type, supplemented by multiple inheritance of interface types.

Unlike Java, the system set of value types (e.g. int, Boolean, char) can be added to using struct definitions. Value types can be automatically cast to object types. This is called boxing. Also unlike Java, strongly typed enumerated types are part of the language. Documentation and user-specified attributes can be included in the source. These are very minor improvements. The languages Java and C# are really very close.

Much like a high-performance Java runtime, the C# source is compiled to a bytecode called Microsoft Intermediate Language (MSIL) that is shared by all .NET languages. The virtual machine never interprets the MSIL, instead using Just In time compilation (JIT) to translate to machine code as needed. This means that compiled .NET program executables (containing MSIL bytecode) are in theory portable to other processor architectures or even operating systems.

C# uses the .NET class libraries like all other languages on the platform. C# is the flagship language for .NET, and apparently the most straightforward mapping to the MSIL.

The goal of C# is to provide a simple, safe, modern, object-oriented, Internet-centric, high performance language for .NET development.
- Programming C#

One of the chief architects of C# is Anders Hejlsberg.

The C# language has been submitted to ECMA as a standard, which is further in the open direction than Java has gone. However much of the class library remains proprietary.

Hello, world

As tradition demands, here is a commandline hello world program in C#.

using System;

namespace HelloNameSpace
{
  public class HelloWorld
  {
   static void Main()
   {
     Console.WriteLine("Hello World!");
   }
  }
}
Several minor variations on this are possible. The Using System; statement could be omitted, and this would require System.Console.WriteLine to be fully specified. The main procedure could be declared to look at the commandline params Main(string args), or main could be declared as type public static int to return an integer. The namespace could be omitted.

The Opinions

Those sceptical of Microsoft see the partial standardisation of .NET as a ploy to lure users in with the promise of "open standards" and lock them in with the closed class library. It is true that the class library is a vital part of the standard of any Object-Orented programming system. See for instance the Java standard, which quite rightly specifies in great detail the classes that must be present. It remains to be seen to what extent this issue will become leveraged as a unique selling point of Microsoft's .NET, and to what extent the mono project can produce a credible open-source clone of this library.

To those that say that C# a rip-off of Java, I say get over it. Java didn't pop fully formed out of a vacuum either. All programming languages learn from their predecessors and contemporaries. Java owes a lot to C++ and Smalltalk. C# owes a lot to Java and a bit to C++, Visual Basic and Delphi.

The real questions are these:

1) Is C# sufficiently innovative to justify its existence on technological grounds, or is it simply Microsoft's attempt to steal Java's thunder, to make a Java-clone that is under their control?

2) Why are C#'s makers so reluctant to admit their debt to Java? If, as they say, they were not overly influenced by Java, then not only did they ignore the most popular programming language to emerge in the 1990s, but they came to the same conclusions independently.

Here are some notes on things that I like and don't like about the language. This is going to be partly informative, partly subjective list, but I hope not a highly subjective one.

Features that I like about C#

  • Hot, creamy Java-flavoured goodness:
    • Garbage collection. No, it's not appropriate for all code, particularly not low-level code like OS kernels and device drivers. But for the majority of end-user applications, it is an idea whose time has finally come.
      Yes, it incurs a speed penalty. Big deal – the speed of your new desktop processor doubles every 18 months. Hardware is cheap, but coders are expensive. Some of that speed is worth spending on more productive ways of programming.
      Since 1970 the programming industry has been through assembler, procedural, Object-Oriented and now OO-gc languages. That's four generations in 30 years, each of which has less than a 50% speed penalty. We are still way ahead of the curve. I'm not saying that GC right for all applications, just for the vast majority of them.
    • Simple, uncluttered syntax. Much like Java and unlike Delphi. This is a consequence of holistic design and a low version number. Delphi doesn't have either of these as it has been built up over a long time from Pascal.
    • The ability to scope variables to the block in which they are used, not the whole procedure. As in
      if (a > 10){int b = 10 ... } .
    • No header files or interface section. Each procedure is declared once and once only. Let the machine do what it's good at – such as generating headers deterministically from the existing data. Also this principle has been taken even further than in Java with the inclusion of attributes and documentation into the source.
      When you write code in C#, you write everything in one place. There is no need for header files, IDL files (Interface Definition Language), GUIDs and complicated interfaces. And once you can write code that is self-describing in this way, then you can start embedding your software, because it is a self-contained unit
        - Anders Hejlsberg.
    • I could go on with the other good java features in C# such as reflection, but you get the idea.
  • Type-safe enumerations were the single thing that I missed the most when coding Java. C# has them.
  • PHP-style Foreach loops. Very nice, in keeping with the theme of the compiler doing a bit of extra work for you to make the common things even easier. Even nicer that any object that implements the IIterator interface can be plugged into it.
  • Built-in sorting and searching in lists for any object that implements the IComparable interface. Good class library design right there.
  • The drag and drop support for web programming looks good, and the drag and drop form builder is good too. Good because it lets you see and tweak the code that it generates. Round-tripping is very necessary for non-trivial use of tools like this.
  • Properties. Yes, Delphi has had these since 1993, but they're still good.
  • Events with built-in multicast. Yum. The Java fans are now cringing and recoiling in horror. But I've done much Delphi, and appreciate this idiom. I've also built the observer pattern for multicast notification in Delphi, and wrestled with the lifetime issues (notifying via a pointer to a now-defunct object will crash the program. It must unhook itself when it frees. It was an ongoing source of bugs). So I really appreciate getting this for free. It's a good way to code, and being built-in, quick and easy means that many people will use it.
  • Following on from that, the slight relaxation of the Java paradigm that "everything is an object". Yes you can do things that way. But you can do things even more easily if you give some leeway where it is needed most. Java enums, or lack thereof is a case in point. It is possible to simulate type-safe enums in Java in an efficient manner using static instances of an object type. But its not a widely used idiom.
    If you're still not convinced, then try to picture some of C# supposedly non-OO things like delegates as simply a shorthand that the compiler translates into a complete class declaration for you during compilation.
  • A built-in assert statement is to be found in the class library under System.Diagnostics.Debug.Assert. Assertions are good - qv for the reasons why. Delphi has had them for years, and Java 1.4 has them.

Features that I am in not sure about

  • Miscellaneous baggage from C and C++.
    • C-style for loops. Easy and flexible. Yes that's good. Allows obfuscation. That's bad.
    • C# has C's function declaration syntax, for e.g. void foo(int x); It is fairly arbitrary if you're not used to it. void is a language hack to avoid putting a specific type where the syntax insists on having one.
    • C#'s switch statements – the thinking seems to have been to keep the syntax as close as possible to C, but to eliminate that old K&R space-saving gotcha that is automatic fall-through. The result is an ungainly hybrid.
    • Operator overloading taken from C++. Overriding +,- etc can be good for numeric classes such as complex number or matrix objects, but how often do you write these? The rest of the time it's a temptation to obfuscate, nothing more. C++-style Implicit type casts via defined cast operators are a double-edged sword.
  • Exceptions. Java enforced a rigorous (and rigid) framework for knowing just which exception a method could throw. It was an innovation, but I don't think it was the new rock and roll, or clearly the right thing – it could be a pain sometimes. C# has a more traditional, laid back C++ or Delphi-style approach – your code doesn't have to tell anyone what exceptions it throws.
  • Unsafe code that can use pointers and system DLLs. Probably a good thing, like Java's native methods, only written in the same language. But it probably will be a source of portability issues.

Features that I don't like

  • Bad baggage from C:
    • The conditional operator ?:. Why is this K&R C baggage still here? K&R C has many construct designed to save typing and space. This optimises for the environment of the late 1960's, where small source file size and RSI were important programmer considerations. We've moved far on from there. Readability is more important than show-off cleverness. And don't assume just because the source is more compact that the generated code will also be smaller and faster. Trivial optimisations should be left to the compiler these days.
    • Allowing code like a = b = c = d;. I am not fond of this, for much the same reasons as above.
    • Arrays can only be int-indexed. Indexing an array on another ordinal type such as an enum or boolean is occasionally very useful in Delphi.
    • Enumerated types are C-style and can be bastardised badly. The examples in the O'Reilly book do this, and worse, use an enumerated type where static integers would be better, and vice versa. It seems that many C/Java programmers don't really get enumerated types.
      C# has no sets of enumeration like in Pascal. Instead you are expected to bastardise the enumeration into a bit mask.
  • Indexers are a dumbed-down version of Delphi's array properties. Why do this when there was a better example at hand? What was Anders Hejlsberg thinking?
  • Namespaces are needlessly more complex than in Java. In Java, the classname and filename have to match.
  • C++-style constructor chaining – ungainly, inflexible syntax. It's odd that constructors, like in C++, are not virtual. The idiom of virtual constructors, in Delphi, is very useful. You can use a variable of type reference-to-base-class-type (which can contain any derived type) to construct an instance of the derived classs by using the class type's virtual constructor.
  • Structs are almost classes but not quite. Who ordered that and why? I understand the arguments in favour of compound, stack-based data items, but structs have grown into classes in all but name. They can implement interfaces fer pete's sake! This is just duplication.
  • Lack of const parameters. Delphi can specify a procedure parameter to be const. This is that happy marriage of a design idiom (It makes code more readable when you know that a parameter is a read only input value to the procedure with no writes allowed) and compiler optimisation (with a const parameter that is a stack value not a heap reference, the compiler can generate faster code in some cases as no local storage need be made for any possible local value changes). C# has value, ref and out parameters, so why not const in?

Further opinions

What do I think of "the promise of .NET"? I think that it's great that VB programmers will get to use VB.NET, a real language with a real class library. I think it's really neat (and labour saving) that it will be the same class library that the other .NET languages use too. Microsoft is clearly putting a lot of effort into this class library. Even better, VB.NET will be a halfway step over to C#.

I think it's interesting that a version of Borland Delphi will use this class library and runtime too. I think it's interesting that a class in one language can subclass a class written in another language. I think it's good that garbage collected languages are centre-stage (and that Java was the start of a trend, not a one-off).

I am worried about the single-vendor issue. Yes, I know that Sun Microsystems is a single vendor for Java too. But they don't have such a vested interest in a single platform as Microsoft. Java is "one language, any platform". .NET is "any language, one platform". Microsoft's platform. That's what it's all really about.

I don't think that the multiplicity of languages is as great an idea as it is touted to be. Would I like to see many languages used in my programming project? No. Not unless there is a very good reason. A group of people all coding on the same project in their own pet language just because they are more familiar with it, or like the syntax better - is not a team, it's a bunch of individuals pulling in different directions.

Familiarity? Anyone who is not capable of picking up a simple friendly language like C# should not be programming. Besides, a large part of the learning curve of a new OO language is the class library.

What would good reason be for a multi-language project? The only one I can think of offhand would be to import legacy code in one language, and do new development in a better one. But what legacy languages? VB6 is not compatible with VB.Net. It remains to be seen what Delphi.NET can do for old Delphi code.

It is however always possible that though all .NET languages are technically equipotent, there may be tasks that are substantially more concise in a particular language. Perhaps, for e.g. PERL.NET for text-mashing? In that case, there may be a case for writing a particular subsystem in a different .NET language.

The theme seems to be that the built in objects are quite rich – and language constructs take advantage of that richness. Good use is made of interfaces here, E.g. the way that the foreach statement leverages the IIterator interface, the list sort works off the IComparable interface.

These features of C# seems at first look to succeed at making the common stuff easy, whilst not preventing you from doing the hard stuff. The language syntax is not quite as simple as Java, but is still straightforward.

C#'s future

The success of .NET and thereby C# as a programming language in the Windows world seems assured. And why not use C#? – you could do worse. If you are going to write a Microsoft Windows application using a Microsoft programming tool, then I'd recommend C# and .NET over Microsoft Visual C++ and Microsoft Visual Basic. I might even (gasp) recommend it over Borland Delphi.

C# may even become popular in the open-source world, with the mono project.

It has been stated that templates and generic programming lie in C#'s future. There wasn't time to do it right for the first release.

C# has potential as a dynamic language. You can feed the reflection classes a series of opcodes and get back a reference to an object of a dynamically constructed new object type. You can attach methods at runtime to an existing object. With the payware version, the C# compiler classes are exposed in the System.CodeDOM namespace, so you can compile text strings to code. Now if Microsoft would build this into the language with some kind of currying operator/keyword/class, then we'd be cooking with gas.

It is however more likely that functional languages will make an appearance on the .NET platform. C# will of course interoperate with them. the .NET platform is said to be suitable for functional languages.


Sources:

Much of my understanding of C# comes from the O'Reilly book Programming C# by Jesse Liberty. It's quite a good book. I recommend it, but bear in mind that I haven't read any others on C# so I can't rank it.

It is typical of the hype and pace that this is the second edition of the book, updated for .NET 1.0. In other words, the first edition was published on a beta release.

However I have read lots of other stuff, including but not limited to the sites that google turned up.

The bizarre opinions are my own.


See also:
Java and C# compared for non-programmers
Microsoft's .NET strategy


C# 2.0

In July 2003, Microsoft has released a specification of C# 2.0, due for release in "early 2004". It includes some new language features. "New" for C# that is, as all of them have been seen before in other languages. Despite this, they are worthy additions.

In order from most important to least important they are:

Generics are parameterised types, and look much like templates do in C++ (and in a proposal for Java). They are implemented by generating the type-independent bytecode at compile time, and when at runtime the template is instantiated for a particular concrete type for the first time, the type-dependant bytecode is generated. This aims to provide high-performance, strongly typed generics without the code-bloat.

Anonymous methods are I believe much like in Java, and are in turn inspired by the lambda operator in scheme. These are not full higher order functions, just the ability to specify throwaway delegates and the like inline rather than declaring a whole new named method in order to attach a small bit of code.

Iterators are functions that can yield more than one value, like generators in Python and other languages before that. It's a lazy list that can generate values as required and returns them via the IEnumerable interface.

Partial types allow a class to be composed of code in more than one source file. This feature is intended to be used for breaking down large classes and as another method of allowing toolkit users to customise the received code (the more normal methods being subclassing and templates).

These are new features not of C# but of the .Net runtime and may also make an appearance in other .NET languages. Visual Basic with templates and anonymous functions? The mind boggles!

Sources:
Microsoft C# 2.0 specification document and discussion thereof on Slashdot under the title"C# 2.0 Spec Released".
Microsoft Developer Tools Roadmap 2003-2005 http://msdn.microsoft.com/vstudio/productinfo/roadmap.aspx