Ok, so I've decided I need to rant a little bit about .NET. This ends up in part being, "What I like about Java that I don't like about C#". I think this is fair though. It's not like C# and .NET were developed in a vacuum. It's not like C# is the first Object Oriented, VM run language. As such I think it's fair to point out where they should have learned from others.
Generics Don't Fully Support Covariant Types
Generic collections in .NET can only handle a single type of object well. You can add a sub-type to a Collection, but if you have two Collections with covariant types, you can not mix them without jumping through hoops.Example
The simple case of adding a single Covariant type works, but when dealing with a Generic Collection of covariant types, it does not.To make it work with AddRange, you have to perform a manual conversion
What's Good About .NET Generics
.NET Generic type information is available at runtime. In Java Generics are implemented as an erasure. Basically this means all of the type checking is done at compile time. The compiler then inserts explicit casts into the code for you. At runtime the code looks the same as if generics were never used. .NET chose not to use erasures but to make the type information available at runtime. This is generally more efficient and less prone to errors or problems with reflections. So good work there.Note: (The Java folks did this so as not to break backwards compatibility. I think that major revisions should be allowed to break backwards compatibility when there are compelling reasons to do so.)
.NET Collections
Are collections classes such a mysterious art?.NET does not have a Set or a Bag. These are generally useful and very common collections. A Set guarantees the uniqueness of elements in List like interface. A Bag can contain any objects. The unique thing about it is that it keeps a count of the same objects.
Example of a Bag
The SortedList and the SortedDictionary both have a Dictionary interface. Why wouldn't the SortedList have an, uhh maybe, a List interface?
The IList interface is so anemic as to be basically worthless. IList does not even have an AddRange method (or an AddAll) to merge the values in one collection into another. It's so limited that it makes it very hard to return interfaces from classes which is a good idea to encapsulate the implementation details of methods.