Neil Gatenby
Neil Gatenby

Reputation: 451

template specialization via extension method

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

Answers (2)

Richard
Richard

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

Gerino
Gerino

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

Related Questions