The joys of new territory in API design

I remember back in the day when we added a first-class notion of properties to the CLR\C#. Up to that time we just had methods and constructors (events came later still). We really didn’t know how to use these things (even though they had existed for *years* in other systems). One of my favorite examples that we actually had checked in as this one from System.Type:

public MethodInfo Methods[string methodName, bool ignoreCase] {get;}

That is right folks, it was basically modeling a two dimension array of method names and a Boolean… usage was something like:

Type t = …

MethodInfo m = t.Method[“IndexOf”, false];

How odd is that? I am sure glad we came to our sense and started to understand what properties are really good for… Just because you technically CAN write code like this doesn’t mean you SHOULD.

Well, it is more than a few years later and we have some new territory in API design and we are fighting the same battle. This time around with generics. Here is the question I just got over an internal alias:

Is it a good practice to reduce the number of overloaded functions by using a generic type?

I have a case where we have about 8 overloaded functions, and I’m proposing we reduce the number of the overloaded functions by 1/2 if we use a generic type for one of the arguments, and this argument is currently of type “XmlReader” in 4 of the functions, and “JobDefinition” type in the other remaining 4 functions. So, if we use a generic type in this case, we will be able to pass in “XmlReader” or “JobDefinition” object. And this will reduce the total number of overloaded functions to 4. So what is your advice?

 

Basically this person is asking if an usage of generics like this is a good one:

public void Foo<T>(T readerOrJobDef, bool value, string name);

public void Foo<T>(T readerOrJobDef, bool value);

public void Foo<T>(T readerOrJobDef);

 

The answer: No. this is not a good usage of generics. Just because you can, doesn’t mean you should… In the case, Anthony Moore does a good job describing what is busted about this plan:

I don’t think generics are right for the scenario you describe, because you can’t constrain them in the right way, and you usually need to constrain generics to do anything interesting with them. While you could potentially reduce your number of overloads by doing this, you would be paying the cost of potentially needing to do late bound invocation or casting, because if the type is not constrained, then it a bit like typing your methods as “Object”. Also, you would open up a number of invalid scenarios when you pass in the wrong type of objects that would have not existed before. From an API consistency point of view, I would not recommend using generics for this.

I could not agree more! Although reducing API bloat is goodness, generics (or any feature for that matter) should only be used where they are really adding unique value.