Impressions of C#

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.

19 Responses to “Impressions of C#”

  1. Jensen Says:

    The internal keyword comes in handy when you are working with several projects in a single solution. (Multiple DLL’s, one application executable.)

    You may create several helper classes inside one of the DLL’s which is only meant to be used inside that DLL. If you make it public, the main executable could also access those classes, if you make it internal the main executable cannot access those classes and functions but the classes are considered public within that assembly.

  2. Lucian Says:

    internal seems to me very similar to java’s package visibility, which is also the default.

  3. Vek Says:

    Delegates and events do not have to be the same pattern. The default pattern (sender, obj) is what microsoft uses for some of their own events (the kind that happens on forms).

    You can declare any number of parameters of any kind (that’s what the delegate part is for). Then when you fire the event, you just call it with those parameters. You are not tied to the sender,obj pattern.

    Delegates and events are very separate things – the event is more responsible for keeping track of who to notify – a list of delegates, really. When the event is fired, it calls its list. So you can think of an event somewhat as just a plain list (array) of delegates. This is why you can can call += on it and so on. Its not quite an array, but it behaves as one to some degree. Its only job is, when called, to call each delegate in its list. Very thin, really.

    The delgate on the other hand is more like a c++ “functor” – in that it stores all information needed to call the handler on a class. E.g., the class instance, and the function to call, and any parameters. So when you’re hooking an event up in C# what you’re really doing is making a delegate (which stores the specific object instance, and the function to call on that instance, and the parameter info), and then you’re adding it to the list of delegates which are on the event. An event is not a stripped down delegate.

    The benefits of this are huge. For example, since a delegate knows everything that is needed to know in order to invoke a function, you can do things like “BeginInvoke” on it to run the function on a different / on the main thread, eliminating any multithreaded GUI problems in one stroke. This includes the ability to RETURN arbitrary data from a different thread on EndInvoke. For GUI synchronization its often useful to use delegates (without events) to realign multithreaded worker execution into serial execution on the main GUI thread once work is complete.

    • Yuriy Says:

      I wouldn’t say BeginInvoke eliminates multithreaded GUI problems in one stroke. It sure helps, but it has its own problems when used in event handlers in a different thread. (Well, WindowsForm’s problems.)

  4. Vek Says:

    Oh, and I forgot. If you’re not aware of CodeProject (google it, I’m not sure if this blog eats links). You should take a peek. It has every possible information you could ever want to know about C#, picked apart, explained in every possible way.

    I honestly wish something like CodeProject existed for other languages/apis, like Qt or Python or etc. Maybe it does, and I just havent found it?

    • Yuriy Says:

      I’ve landed CodeProject a few times when searching for things and it has some nice stuff, though I wish some of it was in the official documentation. It’s also annoying that there are some “articles” that just have some sample code with no or almost no explanation (this is more an issue with other sites I’ve come across).

      The official documentation for Qt (http://doc.trolltech.com/latest/index.html) and Python is excellent IMO and the KDE devs try to maintain a bunch of other useful information at techbase.kde.org.

  5. Alex Launi Says:

    The default visibility for C# class/struct members is private. http://tirania.org/blog/archive/2008/Sep-28.html

  6. turtlewax Says:

    >>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.

    Vek is correct. The “sender, args” pattern is just a convention. You can define events which accept any number of arguments (even zero).

  7. Emanem Says:

    Hi,

    of you article I don’t understand why you’re talking about callback functions for GUI interfaces in C/C++:
    “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.”
    What? I’m sorry but:
    1) C is different from C++
    2) Ever heard of virtual methods ? Those are very good replacement for callback C functions…
    For example look at http://www.gtkmm.org/docs/gtkmm-2.4/docs/FAQ/html/index.html .

    Cheers,

    • Yuriy Says:

      I think you’re getting confused with what virtual methods are. But no, I haven’t tried libsigc++, you are right on that point I was mostly referring to C.

  8. Michael Says:

    I do not really like properties because I think they are unnecessary and they do not really behave like fields, for example you cannot call a function that takes ref values with properties.

    property v1 { get; set; }
    property v2 { get; set; }

    double max (ref double val1, ref double val2)
    {

    }

    calling max with v1 and v2 won’t work.

    Also, in C# you can define operators like +,- etc. but you cannot put them in interfaces. The reason for this is that +, -, etc. are static functions.

    Events in C# are definitivley nicer than in Java, but they also have limitations: you cannot savely use them over thread-boundaries. With Qt, for example, this is possible by using queued events.

    Also I find the .Net class library not as good as the Java one, especially when it comes to multi-threading. There is not even a blocking queue in .Net (well, they added it in 4.0).

    If you want to learn a really great language, have a look at Scala. It runs on top of the JVM, so you can use all Java libraries.

    • Yuriy Says:

      I agree the .NET class library is a little lacking, but so is the Java one, just in different ways. And they are both crufty since nothing has ever been removed (in Java anyway, I haven’t confirmed this in .NET).

  9. Cesar Romero Says:

    All the good things you describe remember Delphi code.

  10. Bruce McGee Says:

    C# was influenced by both C# and Java, as well as Delphi, which Anders worked on previously.

    http://www.simple-talk.com/opinion/geek-of-the-week/anders-hejlsberg-geek-of-the-week/

  11. Barry Kelly Says:

    Some responses:

    * Events are to delegates like properties are to types. To the other commenter that mentioned that events are like lists of delegates, that’s almost right; just like properties have get and set parts, events have add and remove parts. If you don’t specify the add/remove pair manually, a backing field of the delegate type is created and used automatically. However, delegates themselves are linked list nodes, and can be chained with Delegate.Combine – this is what the + operator does by default on delegates. += on an event gets turned into a call to the corresponding add method, which defaults to + on a hidden delegate field. The reason the delegate system is relatively complex is for efficiency; when classes have many possible events but only a few are typically interesting, storing the delegates sparsely is important. Hence the ability to provide custom add and remove halves. This is also part of the reason why subclasses and other classes can’t trigger events; you might decide to change the storage implementation, but the event only describes how to add and remove delegates, not how to invoke them. (Actually, the CLR spec has a way of specifying a method for invocation, so that properties are triples of (add, remove, raise), but C# and almost every other CLR language doesn’t provide it, so it’s not useful in practice.)

    * Virtual exists because methods are non-virtual by default, and they are non-virtual by default because virtual methods have to be designed-for. Virtual methods are like events, they consist of code that can be replaced arbitrarily by a descendant. Very few classes are carefully-enough written such that any of their methods can be replaced like that. By defaulting to non-virtual, this increases maintainability because it’s a lot less likely that third-party code will have taken advantage of virtual methods to rely on unspecified behaviour in classes that weren’t fully designed for them.

    * The correct spelling for an object constraint in a type parameter is ‘class’.

    * The ‘new’ keyword is important for maintainability, to avoid breaking descendants in third-party code when ancestors introduce new methods which happen to clash with existing methods. This is also a reason for not making virtual default and requiring explicit ‘override’ syntax.

    * C#’s enums predate Java’s boosted enum syntax. C#’s enums are much closer to C enums in spirit than even C++ – a boxed enum (i.e. an enum in a location of type System.Object) can even be casted to the corresponding integer type without error (by OO, you would expect an invalid cast exception). Enums also have reasonable support as bitflags (much better than C++), with the [Flags] attribute.

    * Unsafe code is pretty rare and usually due to acute performance issues (usually graphics, scanlines and the like) and complicated interop marshalling.

    * Lambdas are most excellent sugar for anonymous methods, type infererence is very very sweet.

  12. Top Posts « WordPress.com Says:

    […] Impressions of C# Disclaimer: this post is about my recent experience working with C# and has nothing to do with the Mono debate. Over […] […]

  13. links for 2009-09-26 « My place Says:

    […] Impressions of C# « /Linux/FLOSS Blog 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. (tags: software development C# programming events visual studio) […]

Leave a comment