To me it’s not the GC itself that is the biggest issue with Microsoft’s managed languages, but rather the IDisposable interface. The usage pattern of a class that implement that interface is so different (and imposes so much on code that uses such a class) from classes that do not that I find myself implementing IDisposable JUST SO I WON’T HAVE TO REDESIGN ENTIRE SECTIONS OF MY APPLICATION if I find out later that my class needs it. This tends to cause a cascade whereby most of the classes in my project implement IDisposable just to be on the safe side.
If I knew up front which classes would need to implement IDisposable this would not be such a problem. But because I develop iteratively, I do not always have this information a priori. Failure to implement or utilize IDisposable where necessary may result in bugs ranging from the minor to the major; locating and changing the use of classes that are newly IDisposable seems a perfect opportunity to do this.
Although I do not take the memory usage hit from the destructor where the use of IDisposable is unnecessary, the simple need to implement it almost everywhere is highly annoying to me. I get all of this in trade off for GC and bounds checking? I’d rather just try to write good code, honestly. I also lose the ability to execute code when leaving a lexical scope (unless I implement IDisposable, and then it depends on the good graces of the code using my class).
VB.NET and C# may be fine for scripting a few components together, but for anything bigger (or that might need to grow bigger) than that, please give me a real language.