MS.NET Generics - how lame !
May 14th, 2008I was fairly excited about taking advantage of generics in my current C# project. It was going to save me a fair bit of time, and prevent the proliferation of boiler-plate cut and paste code. My requirement was fairly common, I was writting a message handler which had to work with several versions of message. Each message version was fully described by XML in the form of an .xsd. Each message version was a distinct class - so version 2 did not derive from version 1. Using the Dot.Net tool xsd.exe I was able to generate some nice wrapper classes for easy serialization and member access of the differing message versions. So far so good, I thought.
Then I started writting my message handler. Since I wanted to accomodate any message version, I instinctually felt that Dot.Net generics was the means to coding nirvana. I have extensive experience with C++ templates, and felt that this would stand me in good stead. I jumped in, only to discover that Dot.Net generics are only waist deep (when compared to C++ templates) - good thing I didn’t jump in head first.
Let me explain.
Imagine you have a set of classes that you DIDN’T author, but you know they are all very similar. You’d like to work with them in a similar manner. Let’s say they look like this:
class SomeTypeA
{
public void Func()
{
Console.WriteLine("Hello London");
}
}
class SomeTypeB
{
public void Func()
{
Console.WriteLine("Hello New York");
}
}
Now you want to make a function which can work with any of those types
static void Test<T_type>(T_type some_type)
{
some_type.Func();
}
Ooooops !
You can’t do that because Dot.Net hasn’t implemented generics in a manner that is anything similar to template types in C++
You see, in C++ the compiler would wait until you tried to call Test<>() with a particular type, then it would check that that type had a function which matched the name and parameter list for Func(). If it did, it would allow this syntax; but, in C# — Even though it is interpreted and has reflection - the compiler borks.
If you wanted to do something similar, you’d have to use a contraint on the generic function, and the contraint would have to indicate that the T_type implemented a particular interface with a function ‘Func’. Since you aren’t the author of SomeTypeA or SomeTypeB you can’t do anything generic with them, even though you know they both implement the same function ‘Func’.
Of course, you could derive types from them which implemented an interface and simply passed through to the base SomeTypeA or SomeTypeB, but now you have a explosion in types. You’d have -as a minimum- a new interface type, and a new derived type for every unauthored type you wanted to treat generically. so for a very basic project like ours, we’d need 3 new types (an interface and two wrappers) just to use the two existing types generically. Now imagine what happens when different versions support subsets of functionality and the whole thing gets extremely messy very quickly.
All in all Dot.Net generics seems like a half solution. They actually make the developers job more tedious rather than less. Oh well, I guess I shouldn’t be surprised, Dot.Net is like much of what has come out of Microsoft recently, very shiny on the outside, but full of wholes on the inside.
FYI, here’s the equivalent C++ template code, which works just fine with the two types without having to decorate the template function with idiotic information about what interface to use, or necessitating the implementation of an interface and wrapper classes
class SomeTypeA
{
public:
void Func()
{
cout << "Hello World" << endl;
}
};
class SomeTypeB
{
public:
void Func()
{
cout << "Goodbye World" << endl ;
}
};
template<class T_type> void Test(T_type& some_obj)
{
some_obj.Func();
}
int _tmain(int argc, _TCHAR* argv[])
{
SomeTypeA a;
SomeTypeB b;
Test(a);
Test(b);
}
Nice -