Edit: C# 3.0, net 3.5.
I am C++ programmer, so maybe I miss some simple solution in C#.
Simplified example:
I have several classes inherited from class MyBase (with method Inc). The inherited classes may override Inc. I have several overloaded “functions” (static methods) for the inherited classes:
void Print(MyInherited1 i1) ....
void Print(MyInherited2 i2) ....
and so on. Edit: those methods are “external” to the MyBase and MyInherited, they are not part of any of those classes.
I have generics function that modify its argument and call the Print function:
void Transform<T>(T t)
{
t.Inc();
Print(t);
}
Edit: this is simplified example, in real code I cannot convert the Transform method to non-generic one using just polymorphism.
Now, in C++ it would work just like that. However in C# method Inc is unknown. So I specify that T is of type MyBase.
void Transform<T>(T t) where T : MyBase
{
t.Inc();
Print(t);
}
but I still have the problem with Print — there is no such method for the base class.
As a workaround I used ugly (!) solution — PrintProxy where I put several
if (t is Inherited1)
Print(t as Inherited1);
else if ...
How to mix those two concepts — overloading and generics? Nice, C# way?
Thank you in advance for help.
One option in C# 4 is to use dynamic typing:
That will perform the overload resolution for you at execution time – which is basically the best you can do unless you can provide a genuinely generic
Printmethod, as there will only be one version ofTransformgenerated.Note that there’s no real need to be generic at this point – you could replace it with:
I typically find that constraints based on interfaces are more useful than those based on classes, unless I’m also doing something else generic (such as creating a
List<T>which should be of the right actual type).Obviously this dynamic approach has downsides:
objectas a sort of fallback to provide custom error handling, but you still have to wait until execution time)Basically this is just a difference between .NET generics and C++ templating – they’re very different creatures, even if they tackle many similar problems.
Rather than having static
Printmethods, is there any reason you can’t write an abstractPrintmethod inMyBase, and override it in each class? That feels like a more OO solution anyway, to be honest – although obviously it doesn’t make sense if the printing is actually somewhat logically distant from the class itself. Even if you don’t want the actualPrintmethod in the original type hierarchy, might you be able to expose enough functionality to let you write a virtualPrintmethod? I assume all these methods should come up with some similar kind of result, after all.EDIT: A couple of alternative ideas…
Passing in the printer
You can pass in a delegate to do the printing. If you’re calling this from a non-generic context which knows the actual type, you can take advantage of method group conversions to make this simple. Here’s a short but complete example:
Use a type/delegate dictionary
Another option is to have a
Dictionary<Type, Delegate>containing the printing methods. This could either be inlined (if the printing methods are simple) or something like this:Then in your method:
This is another execution time solution though, and you’d need a bit more work if you wanted it to handle further derivation (e.g. walking up through the base classes if it can’t find the relevant printer).