Some very valid criticisms and interesting observations. I personally think C# is too complicated for it’s own good and takes OOP to an unnecessary extreme, which is why I don't use it (or any .NET-based language, really) for anything other than rapid and simple GUI projects.
I do mostly web development work, so lots of Javascript and PHP. I ported a project to Google App Engine a few months ago and I had a lot of fun working with Python, too. I enjoyed Python so much that I even made a couple of personal projects with it, including a command-line Twitter client.
With C#, I feel forced into strict OOP and it just doesn't give me that same level of enjoyment.
I don't like it because I spend 25% more times making my code 25% harder to read and 25% harder to maintain, in order to make it testable and have it "properly" designed.
Most of these boil down to "It's different from C++. I'm used to C++".
Though I do agree that you shouldn't have to check whether an event has any subscribers before raising it. It's possible to DRY that out with an extension method on EventHandler/EventHandler<T>.
Maybe that what's the author wanted to pointed out: if you have garbage collection (at least the way it's implemented in C#/Java) you have to give away scope lifetime of object.
This is annoying because you want determinism for some kind of resources (file, lock, ...) and then you have to manually clean them, which is what you wanted to avoid in the first place with garbage collection.
In C++, if you declare the object on the stack, the destructor will be called when the scope is closed. Which is very handy for e.g. lock.
The thing is, garbage collection could be use together with scope lifetime (aka RAII) just let the programmer choose which is best/more convenient for him given his resources.
I agree. I think the author does understand the difference between scope, object lifetime and manual/GC object management.
The article is clearly written for pogrammers coming from C++ to C#, which there are a lot of, including myself. I like both C++ and C# a lot but have to admit that managing object lifetime in C# is one of the things I really dislike. There's the suggestion that RAII is reasonable in C# but for me always ends up being a headache.
As others have noted, this could have been written against many VM/GC based languages and not just C#. That said, it's the FUNDAMENTAL difference between the 2 types of languages and thus the comparison is moot. It's like getting into a limo and saying it doesn't feel like a motorcycle. I'm not convinced the author understands this...
The first 2 points shows such fundamental misunderstanding of garbage collection that it's hard to take this article seriously.
Every garbage-collected language has this "problem". The "problem" (objects are reclaimed an unspecified time after they have been determined as unreachable by GC) is a fundamental property of garbage collection (at least the most frequently used, non-ref-counted GC).
It's also well accepted that when it comes to releasing resources other than memory, programmers should be doing it more explicitly and not rely on GC and that's why C# has using statement and IDispose interface. It's no worse than in non-GC languages where you have to do such manual management for everything and it applies to all GCed languages, not just C#.
He's complaining about C# crashing on broken code (where program used an unsafe operation to get at raw memory of the object without telling GC that the object cannot be reclaimed). C#, of course, is to blame, not the programmer who wrote broken code.
The rest is just a bunch of "I know better" opinions.
I'm sure if they had a chance, they would fix a thing or two but it's exceedingly easy to spend a few minutes thinking about an issue, decide it's broken and broadcast one's beliefs in a blog post.
The hard part is thinking about trade offs in alternative designs, unintended consequences etc. I'm pretty sure C# designers had good reasons for most of the things a guy who blames language for crashing on broken code criticizes.
The only really valid criticism is the one about event handlers, and that kind of makes sense if you consider symmetry with regular nullable references. "Languages shouldn't allow null references" is a more valid and interesting topic, but hat ground has been well covered.
Also I've nearly always done the first pattern on Chris Burrows page, although Jon Skeet recommends differently on his multi-threading event page http://www.yoda.arachsys.com/csharp/threads/lockchoice.shtml which (I think but I must ask him) is really more about avoiding the lock(this).
Yes, there are mistakes in the details, but the actual points are valid. Default comparison behaviour is error-prone, operator overloading is badly designed, and the subscriber-less events exceptions are a kludge.
In most object-oriented languages, there is a
very specific time when an object constructor is
called (namely, when an object is instantiated) and
when its destructor is called (namely, when it falls
out of scope)
Is that actually correct? From what I recall and from what I see after a bit of Googling, it would appear that most object oriented languages either don't even have destructors, or if they have they are called when the object is garbage collected, not when it goes out of scope.
21 comments
[ 3.1 ms ] story [ 56.4 ms ] threadWith C#, I feel forced into strict OOP and it just doesn't give me that same level of enjoyment.
Though I do agree that you shouldn't have to check whether an event has any subscribers before raising it. It's possible to DRY that out with an extension method on EventHandler/EventHandler<T>.
1. Default Object Lifetime Is Non-Deterministic 2. Object Lifetime is Not Determined by Scope
For a GC based language? Seriously? Sorry, but this article should not be voted up. One wonders if it was done so to peddle the Author's book.
In C++, if you declare the object on the stack, the destructor will be called when the scope is closed. Which is very handy for e.g. lock.
The thing is, garbage collection could be use together with scope lifetime (aka RAII) just let the programmer choose which is best/more convenient for him given his resources.
The article is clearly written for pogrammers coming from C++ to C#, which there are a lot of, including myself. I like both C++ and C# a lot but have to admit that managing object lifetime in C# is one of the things I really dislike. There's the suggestion that RAII is reasonable in C# but for me always ends up being a headache.
Every garbage-collected language has this "problem". The "problem" (objects are reclaimed an unspecified time after they have been determined as unreachable by GC) is a fundamental property of garbage collection (at least the most frequently used, non-ref-counted GC).
It's also well accepted that when it comes to releasing resources other than memory, programmers should be doing it more explicitly and not rely on GC and that's why C# has using statement and IDispose interface. It's no worse than in non-GC languages where you have to do such manual management for everything and it applies to all GCed languages, not just C#.
He's complaining about C# crashing on broken code (where program used an unsafe operation to get at raw memory of the object without telling GC that the object cannot be reclaimed). C#, of course, is to blame, not the programmer who wrote broken code.
The rest is just a bunch of "I know better" opinions.
C# was actually designed but some of the best, thoughtful language designers (like Anders Hejlsberg http://en.wikipedia.org/wiki/Anders_Hejlsberg).
I'm sure if they had a chance, they would fix a thing or two but it's exceedingly easy to spend a few minutes thinking about an issue, decide it's broken and broadcast one's beliefs in a blog post.
The hard part is thinking about trade offs in alternative designs, unintended consequences etc. I'm pretty sure C# designers had good reasons for most of the things a guy who blames language for crashing on broken code criticizes.
Only problem I typically have is libraries that overuse sealed and final keywords.
Also I've nearly always done the first pattern on Chris Burrows page, although Jon Skeet recommends differently on his multi-threading event page http://www.yoda.arachsys.com/csharp/threads/lockchoice.shtml which (I think but I must ask him) is really more about avoiding the lock(this).
The rest of the points are valid for discussion.