Wednesday, January 30, 2008

Things that are silly in .NET

Collections:


List defines a "Find" method that takes a delegate - IList does not.
This could be defined by IEnumerable basically providing you with a arbitrarily filterable enumerable thingy.

List defines "AddRange" method - IList does not. This could be defined at the ICollection level, and allow you to add any enumerable to the collection.

These problems restrict the usefulness of the collections when they are declared by their interface and encourage the developer to return the concrete type and not the interface.
Bad for several reasons.

I've made a generic static finder method that provides the same functionality as List.Find, List.FindAll and so on, but has the added bonus of being able to search anything that is enumerable. Generic and typesafe.

Example of syntax:
IList<string> myList = new List<string>();
myList.Add("Hello?");
myList.Add("Goodbye!");
myList.Add("Error!");

ICollection<string> items = CollectionSearcher.FindAll(
myList, delegate(string s)
{ return s.EndsWith("!"); });
"items" would contain 2 strings - "Goodbye!" and "Error!".

Wouldn't this have been better in the base library?

XML Serialisation:


Does not support nullable types (Nullable) and provides only cumbersome support for the concept of null primitives by other means - for each property "e.g. 'PropX'", you must supply a second 'magic' boolean property that states if the property has been set (e.g. 'PropXSpecified'). This makes dumb BOs bigger and messier than they need to be and means that you have to check two properties to get a value. Rubbish. I know the Nullable support was added to .net 2.0 after serialisation was added, but it can't take much work to fix it. In fact, I've had to make my own ISerializable implementation that supports nullables so I don't have the property specified nonsense all over the place.

Does not support serialisation / deserialisation of properties that are declared as returning a collection interface (e.g. IList). Again, encourages the developer to return the concrete type and not the interface.

Has no way of supporting Abstract / Interface types. For example, you cannot serialise / deserialise something which is defined as extending / implementing a non-concrete type. Bad for flexibility - BOs must reference specifically about all concrete types they can hold.


Reflection:


Not at all obvious how you get the name of an Attribute from an AttributeInfo object that you have found by reflecting an assembly.

e.g.

IList<CustomAttributeData> attrs =
CustomAttributeData.GetCustomAttributes(
Assembly.ReflectionOnlyLoad(assemblyName.FullName));

foreach (CustomAttributeData data in attrs)
{
if (data.Constructor.DeclaringType.FullName == typeof(XXXAttribute).FullName)
{
// We've found an assembly with the attribute we're interested in
}
}

Wouldn't it make sense to be able to get the type directly from the CustomAttributeData?
(e.g. via a property 'Type data.AttributeType')