Sunday, October 21, 2007

Consuming generic types as a generic parameter

What is he talking about? Well, I have a hard time expressing myself when it comes to generics. I'm trying to make a library I can use across projects

This is what I want to do:

interface BusinessEntity<T>{...}
class EntityList<T> where T : BusinessEntity<TT>{...}

That way I can let my domain objects implement the BusinessEntity interface and they can be consumed by my EntityList. In the following I have a domain class called Document.

//defining Document
class Document : BusinessEntity<int>{...}
//creating instance
EntityList<Document> list = new EntityList<Document>();

To me this all makes sense. Sadly it doesn't compile :( The problem is that TT in the EntityList is not defined. As far as I know I have to define both T and TT on EntityList even though TT is given once I have defined T. Now it loks like this:

class EntityList<T,TT> where T : BusinessEntity<TT>{...}
//creating instance
EntityList<Document,int> list = new EntityList<Document,int>();

I'm not to happy about the extra generic parameter on the EntityList. Once T is defined, there can be only one valid type of TT. But because of the way you have to define it, the compiler will not complain about the TT, but actually about the fact that T doesn't implement BusinessEntity<TT>. This means that if TT is defined as string for instance, the error message from the compiler will be: Error, Document does not implement the interface BusinessEntity<string>. This will make no sense to the programmer trying to use the class.

If you have any solution to this, please let me know :)

1 comment:

  1. Well I guess that there is no true answer to that one... I do not have a solution right out of the box.

    Just remember... Because one CAN use generics, doesn't meen that one SHOULD use them. If you have a problem finding the one true solution and the one you have seem a bit silly, ask yourself if you are attacking the problem from the right flank. Maybe you could solve the same problem in another way.

    A few times I've been into my knees in what I thought was a brilliant design using generics, only to refactor it later, because I've dug my self into a hole :)