How would you do specialization in C#?
I'll pose a problem. You have a template type, you have no idea what it is. But you do know if it's derived from XYZ
you want to call .alternativeFunc()
. A great way is to call a specialized function or class and have normalCall
return .normalFunc()
while have the other specialization on any derived type of XYZ
to call .alternativeFunc()
. How would this be done in C#?
If you just want to test if a type is derrived from XYZ, then you can use:
If so, you can cast "theunknownobject" to XYZ and invoke alternativeFunc() like this:
Hope this helps.
Some of the proposed answers are using runtime type info: inherently slower than compile-time bound method calls.
Compiler does not enforce specialization as well as it does in C++.
I would recommend looking at PostSharp for a way to inject code after the usual compiler is done to achieve an effect similar to C++.
Assuming you're talking about template specialization as it can be done with C++ templates - a feature like this isn't really available in C#. This is because C# generics aren't processed during the compilation and are more a feature of the runtime.
However, you can achieve similar effect using C# 3.0 extension methods. Here is an example that shows how to add extension method only for
MyClass<int>
type, which is just like template specialization. Note however, that you can't use this to hide default implementation of the method, because C# compiler always prefers standard methods to extension methods:Now you can write this:
If you want to have a default case for the method that would be used when no specialization is provided, than I believe writing one generic
Bar
extension method should do the trick:I was searching for a pattern to simulate template specialization, too. There are some approaches which may work in some circumstances. However what about the case
It would be possible to choose the action using statements e.g.
if (typeof(T) == typeof(int))
. But there is a better way to simulate real template specialization with the overhead of a single virtual function call:Now we can write, without having to know the type in advance:
If the specialization should not only be called for the implemented types, but also derived types, one could use an
In
parameter for the interface. However, in this case the return types of the methods cannot be of the generic typeT
any more.By adding an intermediate class and a dictionary, specialization is possible.
To specialize on T, we create an generic interface, having a method called (e.g.) Apply. For the specific classes that interface is implemented, defining the method Apply specific for that class. This intermediate class is called the traits class.
That traits class can be specified as a parameter in the call of the generic method, which then (of course) always takes the right implementation.
Instead of specifying it manually, the traits class can also be stored in a global
IDictionary<System.Type, object>
. It can then be looked up and voila, you have real specialization there.If convenient you can expose it in an extension method.
See this link to my recent blog and the follow ups for an extensive description and samples.
In C#, the closest to specialization is to use a more-specific overload; however, this is brittle, and doesn't cover every possible usage. For example:
Here, if the compiler knows the types at compile, it will pick the most specific:
However....
will use
Foo<T>
even forTSomething=Bar
, as this is burned in at compile-time.One other approach is to use type-testing within a generic method - however, this is usually a poor idea, and isn't recommended.
Basically, C# just doesn't want you to work with specializations, except for polymorphism:
Here
Bar.Foo
will always resolve to the correct override.