Reputation: 451
In C#, I'd like to have a method of my generic class behave in different ways, using something akin to explicit template specialization
I see from a related post that such a thing might be possible in C#, using extensions, but my code is not behaving as desired: I want one behaviour for Thing<int>::Method()
and another behaviour when <T>
is anything other than <int>
.
I have
using System;
public interface IThing
{
void Method();
}
public class Thing<T> : IThing
{
public void Method()
{
this.Specialization<T>();
}
}
public static class ThingExtensions
{
public static void Specialization<T>(this Thing<T> cls)
{
Console.WriteLine("Thing<T> specialization");
return;
}
public static void Specialization(this Thing<int> cls)
{
Console.WriteLine("Thing<int> specialization");
return;
}
}
public class Program
{
public static void Main()
{
var t = new Thing<float>();
t.Method();
t.Specialization();
var i = new Thing<int>();
i.Method();
i.Specialization();
}
}
But this outputs
Thing<T> specialization
Thing<T> specialization
Thing<T> specialization
Thing<int> specialization
Rather than
Thing<T> specialization
Thing<T> specialization
Thing<int> specialization
Thing<int> specialization
The obvious question "why not just call Specialization<T>
rather than Method
?" is hopefully answered by my inclusion of the interface class - I am trying to fit into its framework.
I can see that Specialization<T>
is a match for Specialization<int>
, but I'm surprised that the latter is not regarded as a better match!
Upvotes: 2
Views: 1127
Reputation: 108975
The call to this.Specialization<T>();
is resolved when the containing method is compiled. At that point T
is anything.
Some languages with generic support (eg. C++) resolve the implementation of generic methods as late as possible, when all type parameters (or in C++'s case all template parameters: in C++ template parameters are not restricted to types).
But C# does not take this approach. This does have the advantage of making the compilation model simpler, but it is less powerful.
(Personally I would like the ability to explicitly specialise, including partial specialisation, but I also recognise this has challenges for the way types are resolved in .NET.)
Upvotes: 1
Reputation: 1983
Unfortunately, when you call Method()
it is running as Thing<T>
, not knowing it is Thing<int>
. You can use reflection to find this out, or (better idea):
if(this instanceof Thing<int> x)
x.Specialisation();
else
this.Specialisation();
Alternatively you can declare Method()
as virtual
and create IntThing : Thing<int>
with override void Method(){...}
Upvotes: 2