Disclaimer: this post is about my recent experience working with C# and has nothing to do with the Mono debate.
Over the last month and a half I’ve been working on an application using C#, .NET, and Windows.Forms in Visual Studio 2008. I started by learning C# (unfortunately from some outdated materials). At first it seemed like they took the worst instead of the best things from Java and C++, but overall I’ve gotten to like the language. Here are some of my thoughts on it, some more elaborated than others.
I like properties[1]. They get rid of a lot of clutter and allow you to do some neat things. They also tend to much reduce people’s tendencies to use public fields. I really like VS’s “encapsulate field” option that generates a property from a field for you.
I don’t understand the need for the internal keyword or why this is the default visibility.
I like how there are interfaces as in Java. I’m not sure if I like how there is no multiple inheritance as in C++ and Python. I’m not sure if I like how implementing an interface and extending a class uses the same syntax.
Generics are nice, but C# has the same historical wart as Java where the set of Collections in the system library includes old non-generic classes that are still used.
I miss C++’s consts everywhere. No const parameters or const methods or const return types in C#.
I like how you can write unsafe code. I haven’t actually made use of it yet, but I think this is a huge advantage over Java.
The Reflection API can be useful, but it’s not nearly as easy as Python’s getattr() & co.
String comparison with == by value is a great improvement from Java.
C# has operator overloading. Yay.
Events
The biggest thing C# has over Java for me is events.
Events suck in Java. Most of the time you end up having to define a whole extra class to handle one. Since handling an event is so tedious, they are often quite generic and you have to check the arguments for what actually happened. The one good thing about it is it’s clear OOP with no magic.
Handling events in pure C/C++ usually involves callbacks with function pointer voodoo. Qt provides a very nice type safe layer with signals and slots, with an almost ideal syntax, but the implementation is questionable and magical.
C# has events built into the language. A class can have events with specific arguments and can invoke them much like Qt signals. Events have types that identify their signatures, so it’s type safe and no magic. However, that’s also where it gets clunky. For every event with different arguments you need to also declare a delegate for the type (from what I understand but haven’t read into yet, C# 3.0 provides some generics to make this less tedious). When connecting an event, you need to create an instance of the delegate.
In addition, .NET requires that all events take two arguments: a sender object (nice!) and an EventArgs object with the rest of the data (yuck!), which makes the whole thing almost as bad as Java. But without that restriction, which is only for compliance with other .NET languages, it’s almost as nice as Qt signals.
Unfortunately, as with many parts of C#, there are some restrictions on how events can be used that make the language seem incomplete and/or don’t quite jive with what seems like sensible OOP. Only a class that declares an event can call it, not a subclass. Events are null if there is nothing connected to them, and you have to check for this. The race condition implied there is quite disturbing, but I don’t think I’ve run into a problem yet. In most cases, to workaround both problems, you have to declare a separate method that does this check and invokes the event, which makes the whole thing again more tedious and clunky than it should be.
Events seem to be objects. They have a type and operators. But you can’t just use them as objects, can’t pass them around. An event is basically a delegate with stripped down functionality and this stripping down is built into the language, which seems rather wonky. Of course, the only reason I would want to do any of these things is to work around problems in Windows.Forms. Also maybe because I’m spoiled by python where everything is on equal standing as an object.
Limitations and Warts
In addition to the problems with events, there are some other limitations I’ve run into.
virtual keyword: This is one of the aforementioned carryovers from C++ that is not in Java that I don’t undersand why it was brought back in C#[2]. There is probably a good technical reason for it, but API-wise it’s just annoying.
Name hiding: C# allows you to create members in subclasses that hide (no polymorphism) rather than override base class members. The language has the “new” keyword to do this, but does not require its use. I think most of the time hiding methods like this without polymorphism is just asking for trouble, and the keyword seems almost useless if it is not required. The compiler does give a warning when you hide something without using new, so I told VS to report those warnings as errors.
You can have type constraints on generic arguments, but for some reason this type cannot be an enum. It also can’t be object, which, while redundant, seems like a rather arbitrary limitation for a language to make.
I expected C# enums to be fancy like Java’s, but it seems despite being derived from a class, they’re mostly limited to C++ enums.
Extension methods are neat, but why aren’t there extension properties?
I have yet to explore lambdas (C# 3.0), but delegates as anonymous methods seem a bit clunky sometimes.
Unsafe code in C# seems like it could cause a whole new set of problems other than those in C++, since everything is allocated on the heap and objects are managed. There are various keywords to deal with pointers to data residing in objects managed by the VM, but it seems like the combination is just asking for trouble.
Overall, while it has its sometimes strange limitations, I rather like C# and it sure beats Java. When/if I get to writing unsafe code, I’ll see how it really compares to C++. .NET, Windows.Forms, and Visual Studio are another story, but this is getting long enough so I’ll leave them for another post.
[1] I wish the MSDN site would work in Konqueror, but I’m not terribly surprised.
[2] Supposedly C# was based on C++ and not Java, but I find this hard to believe.