There's not much more to say about XNA: stuff just works. It's the Python philosophy of batteries included: you have content processing, model rendering, sound and music, basic collision classes, 2d sprite rendering including fonts all built in already and no matter what kind of game you're making, you can have a prototype up in a day or two.
So, C#. The short version is that it's C++ with most of the stuff you can shoot your leg off removed and a ton of convenience candy added. Most useful stuff added:
- Delegates: function pointers done right
- Events: well, sort of glorified lists of delegates, but convenient anyway
- Properties: make your stuff look exactly like public member variables, but use set/get functions under the hood
- Interfaces: kind of what pure virtual classes are in C++, only acknowledged as such
- Standard interfaces for a lot of things, like serialization, iteration and containers
- Reflection.
- Well defined initialization order. Static class members (and static constructors) are initialized before the first object of a class is created and before the first static method is called.
Yeah, you get most of that stuff in C++, too, but you have to use nonstandard libraries and usually deal with quirky template syntax.
Stuff removed:
- HEADERS. I can't say enough how much time that saves.
- Along with that, long compile times.
- Implicit overloads of virtual functions. You have to specify exactly which class defines the function and which implements it.
- Implicitly passing arguments by reference. In C#, the caller has to express consent that the integer passed to the function may be modified.
- friend. Initially, I missed that one greatly, but after a bit, it became clear it's a good thing. It's too tempting to declare classes friends just to give one exclusive access to one or two members of the other. There's almost always a better way.
- const. I'm a bit on the fence about that. It adds complexity, but also value. You can emulate const with interfaces (and that's what the container interfaces do: there's IEnumerable for read access to containers and ICollection for write access), but still.
- Explicit memory management
- Multiple inheritance outside of interfaces
- Macros
- Full featured templates
You still get Generics to replace templates. They're not as powerful as C++ templates in what they can do (you can only call member functions of objects of template argument type if you specified the type needs to have a certain interface), but their usage is so much more powerful that it makes up for it. First, there cannot ever be any strange generic instantiation errors. If your generic parameter meets the declared restrictions, you can instantiate the generic. Second, and the mind boggles massively here, YOU CAN INSTANTIATE THEM AT RUNTIME. Yes. You can have a function that takes an arbitrary object as a parameter, looks up the object's type, instantiates a suitable generic for it, then lets that generic do the work.
You can just be immensely productive in C#. I wanted to have protobuf in the little XNA game I'm writing to get to know it, but couldn't get the semi-official protobuf-net to work on the XBox. I realized that Monday evening. So I decided to write my own crude version, thinking maybe I'd get it to handle ints and floats properly and be done then. Now it's two days later (plus sleep) and my little thing supports all primitive types and many of the XNA classes, ALL containers (Well, I still have to figure out how to handle containers of containers properly), structs and classes, it doesn't care whether elements are implemented as fields or properties, it handles inheritance, it can be easily extended, it can automatically only store those elements that haven't changed relative to a reference, handles NULL references and empty containers, it's extremely flexible (all integer types are alike, all containers are alike and can be swapped freely) and uses less bytes than protobuf. And it can store object spaghetti just fine, so it can be used as an easy savegame system.
And then there's Visual Studio. While I admit I'm not a fan of IDEs and two EMACS windows side by side suit me fine, thank you very much, I have to say that the automatic completion and checking stuff as you type it (which would never be possible in this quality with C++) and the refactoring functions, while a tad limited, are still quite useful. Remember that time when you had an oddly named function, but couldn't rename it because it would lead to changes all over the place and global search/replace wouldn't work because of that other function with the same name (where it truly fits)? Well, here you can tell the IDE to rename the function for you and do all the required changes. (Yeah, that's also possible in Eclipse. Provided you write Java.)
Comparisons with other languages you may like:
- Java. Haven't looked at that in recent revisions and it has improved a lot (also has Generics), but my uninformed impression is that C# does whatever Java does, only more, and better. (Yeah, yeah, cross platform support. /me points at Mono. Even available on the Wii.)
- Python. While it's initially way easier to write code in Python and it's a great language for what it aims at, it's simply easier to do reasonably complex things in a more restrictive environment. Have you ever debugged Python? I rest my case.
What I don't like so much is rather ignorable:
- There's the standard Windows development problem that there's no canonical place for development libraries. It's less bad than in C/C++ where your project also has to find the headers, though.
- The garbage collector is said to kick in every second or so and taking 20+ms to complete, blocking your app, if you're not careful. Haven't experienced that myself so far, really.
- Yeah, the speed loss. Especially on the XBox, where it's about a factor of 10 slower than it should be.
And before the obvious question comes up: No, no straight Armagetron port for the 360 is in the works. It wouldn't be possible. XBox apps are only allowed to communicate over the LIVE network, general sockets are not available. And without the ability to jump on all those awesome servers, what would Armagetron be? BUT: Of course, my test project is a Tron Lightcycle clone. It's my default test project
