One option in C# 4 is to use dynamic typing:
void Transform<T>(T t)
{
t.Inc();
dynamic d = t;
Print(d);
}
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 Print
method, as there will only be one version of Transform
generated.
Note that there's no real need to be generic at this point - you could replace it with:
void Transform(MyBase t)
{
...
}
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:
- It requires .NET 4.0
- It's slower than a compile-time binding (although it's unlikely to be significant unless you're calling it a heck of a lot)
- There's no compile-time validation (you can add an overload which takes
object
as 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 Print
methods, is there any reason you can't write an abstract Print
method in MyBase
, 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 actual Print
method in the original type hierarchy, might you be able to expose enough functionality to let you write a virtual Print
method? 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:
using System;
class Test
{
static void SampleMethod<T>(T item, Action<T> printer)
{
// You'd do all your normal stuff here
printer(item);
}
static void Print(string x)
{
Console.WriteLine("Here's a string: {0}", x);
}
static void Print(int x)
{
Console.WriteLine("Here's an integer: {0}", x);
}
static void Main()
{
SampleMethod(5, Print);
SampleMethod("hello", Print);
}
}
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:
static readonly Dictionary<Type, Delegate> Printers =
new Dictionary<Type, Delegate>
{
{ typeof(MyClass1), (Action<MyClass1>) Print },
{ typeof(MyClass2), (Action<MyClass2>) Print },
{ typeof(MyClass3), (Action<MyClass3>) Print },
};
Then in your method:
Delegate printer;
if (Printers.TryGetValue(typeof(T), out printer))
{
((Action<T>) printer)(t);
}
else
{
// Error handling
}
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).